home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / CALib & You… / Source / CASample / CAS_Doc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-07  |  65.8 KB  |  2,937 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        CAS_Doc.c
  3.  
  4.     Contains:    Document window and file handling routines.
  5.  
  6.     Written by:    David H Nelson
  7.  
  8.     Copyright © 1993-1995 ComponentWorks, All rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.                  05/15/95    DAS        moved common drag handler and CALib callback
  13.                                      installation code into individual routines
  14.         --------------------------------------
  15.                  05/15/95    RB        Adding CALib Install calls for "Container" handlers
  16.         --------------------------------------
  17.                  05/09/95    SJF        Tweaks for WWDC Demo
  18.         --------------------------------------
  19.  
  20.                  05/08/95    SJF        Reenable Drag handler install section, release
  21.                                      handlers BEFORE closing doc...
  22.         --------------------------------------
  23.  
  24.                  04/23/95    RB        Modified Doc_New & Doc_Open to register register
  25.                                      focus handlers with CALib.
  26.         --------------------------------------
  27.  
  28.                  04/22/95    DAS        cleaned up and added error checking.
  29.         --------------------------------------
  30.                  03/29/95    RB        Changed DocPtr->fRefNum initial value from -1 back
  31.                                      to 0.  There's code which depends on 0 as the initial
  32.                                      value.
  33.  
  34.                                      Fixed Doc_New & Doc_Open to make sure the root frame
  35.                                      of a window is clipped to the cont area - scrollbars.
  36.         --------------------------------------
  37.                  03/27/95    DAS        improved document clean/dirty handling,
  38.                                      as per Rick/Steve requests.
  39.         --------------------------------------
  40.                  03/17/95    RB        Added support for Bento storage model
  41.         --------------------------------------
  42.                  01/25/95    RB        Added support for internal scrap format
  43.         --------------------------------------
  44.                  01/20/95    RB        Added docMouseInItem()
  45.         --------------------------------------
  46.  
  47.                  01/18/95    DHN        Global function and variable name changes to suggest
  48.                                      OOP design. Split app.c file into app.c, win.c, doc.c,
  49.                                      item.c, and util.c.
  50.         --------------------------------------
  51.                  01/17/95    DAS        changed all FrontWindow() calls to
  52.                                      App_GetFrontDocWindow() to account for
  53.                                      floating windows. Added Win_IsToolWindow().
  54.                   1/16/95    DHN        Massive improvements including, multiple window
  55.                                       support, new window offsetting and naming, pref
  56.                                     file support, file saving/reading, cursor tracking,
  57.                                     PowerPC support, window update/activate in dialog
  58.                                     filter, item drawing/selection/cut/copy (not paste),
  59.                                     drag & drop (no drop yet), window scrolling, get
  60.                                     info dialog, Select all menu item, Tools menu.
  61.                     through
  62.                  12/23/94    DHN        Created CASample from existing Light Software
  63.                                      application framework.
  64.         --------------------------------------
  65.                   1/24/93    DHN        Added code to ignore the enter key. Fixed page 
  66.                                       flipping animation by using current GrafPort in 
  67.                                       local coords rather than new GrafPort with global
  68.                                       coords. Fixed findAgain to actually do something.
  69.                  11/20/93    DHN        Created.
  70. */
  71.  
  72. #ifdef USE_CALIB
  73. #include "CALib.h"
  74. #include "CAS_CAUtil.h"
  75. #endif
  76.  
  77. #include "CAS_Globals.h"
  78. #include "CAS_Error.h"
  79. #include "CAS_Doc.h"
  80. #include "CAS_Win.h"
  81. #include "CAS_App.h"
  82. #include "CAS_StringTools.h"
  83. #include "CAS_Content.h"
  84.  
  85. #include <string.h>
  86.  
  87. void GetPlatformScrapTypeList (ResType typeArray[]);
  88.  
  89. //----------------------------------------------------------------------
  90. //     local prototypes
  91.  
  92. #if defined(__cplusplus)
  93. extern "C"
  94. {
  95. #endif
  96.  
  97. static OSErr Doc_InstallDragHandlers(
  98.     DocPtr        theDoc,
  99.     WindowPtr    theWindow );
  100. static OSErr Doc_InstallCALibHandlers(
  101.     DocPtr        theDoc,
  102.     WindowPtr    theWindow,
  103.     Boolean        isNewDoc );
  104.  
  105. #if defined(__cplusplus)
  106. }
  107. #endif
  108.  
  109.  
  110. //----------------------------------------------------------------------
  111. //    Doc_InitData - initialize DocData instance.
  112.  
  113. void Doc_InitData(
  114.     DocPtr    theDoc )
  115. {
  116. Rect    emptyR;
  117.  
  118.     if (theDoc != nil)
  119.     {
  120.         SetRect( &emptyR, 0, 0, 0, 0 );
  121.  
  122.         theDoc->fileRefNum = (0);
  123.         theDoc->fileLocked = false;
  124.         theDoc->filler1 = false;
  125.  
  126.         theDoc->changed = false;
  127.  
  128.         theDoc->hPrint = nil;
  129.  
  130.         theDoc->hScrollBar = nil;
  131.         theDoc->vScrollBar = nil;
  132.  
  133.         theDoc->hScrollBarRect = emptyR;
  134.         theDoc->vScrollBarRect = emptyR;
  135.  
  136.         theDoc->contentRect = emptyR;
  137.         theDoc->documentRect = emptyR;
  138.  
  139.         theDoc->undoData = nil;
  140.  
  141.         theDoc->contentColl = (ElemCollPtr) NewPtr (sizeof (ElemColl));
  142.         ElemColl_Init(theDoc->contentColl, theDoc);
  143.  
  144.         theDoc->insertionPoint.v = 20;
  145.         theDoc->insertionPoint.h = 20;
  146.  
  147.     }
  148. }
  149.  
  150.  
  151. //----------------------------------------------------------------------
  152. //    Doc_GetDirty - called to find out if the doc has been modified.
  153.  
  154. Boolean Doc_GetDirty(
  155.     DocPtr    theDoc )
  156. {
  157. Boolean retVal = false;
  158.  
  159.     if (theDoc == nil)
  160.         return false;
  161.  
  162. #ifdef USE_CALIB
  163.  
  164.     retVal = CAHasDocumentChanged (theDoc->partDocRef);
  165.     
  166. #endif
  167.  
  168.     if (theDoc->changed) retVal = true;
  169.     
  170.     return (retVal);
  171.     
  172. }
  173.  
  174.  
  175. //----------------------------------------------------------------------
  176. //    Doc_SetDirty - called whenever the document changes. It sets the
  177. //    doc's changed field as specified and does anything else the app needs.
  178.  
  179. void Doc_SetDirty(
  180.     DocPtr        theDoc,
  181.     Boolean        isDirty )
  182. {
  183.  
  184.     if (theDoc != nil)
  185.     {
  186.         if (isDirty != Doc_GetDirty (theDoc))
  187.         {
  188.             theDoc->changed = isDirty;
  189.             App_AdjustMenus (Doc_GetWindow (theDoc));
  190.         }
  191.     
  192.     }
  193. }
  194.  
  195.  
  196. //---------------------------------------------------------------------------
  197. // Set the coordinate system to that of our document’s, based on the scroll bars.
  198.  
  199. void Doc_SetGrafOrigin(
  200.     DocPtr    theDoc )
  201. {
  202. Point    docOrigin;
  203.  
  204.     docOrigin.h = 0;
  205.     docOrigin.v = 0;
  206.  
  207.     if (theDoc != nil)
  208.     {
  209.         if (theDoc->hScrollBar != nil)
  210.             docOrigin.h = GetControlValue( theDoc->hScrollBar );
  211.         if (theDoc->vScrollBar != nil)
  212.             docOrigin.v = GetControlValue( theDoc->vScrollBar );
  213.     }
  214.  
  215.     SetOrigin( docOrigin.h, docOrigin.v );
  216. }
  217.  
  218. //---------------------------------------------------------------------------
  219. // Doc_AddItemPict - Add an item to our document at thePt (doc coords) 
  220. // using the picture thePict.
  221.  
  222. ElemPtr Doc_AddItemPict(
  223.     DocPtr        theDoc,
  224.     PicHandle    thePict,
  225.     Point        thePt )
  226. {
  227. Rect        theRect;
  228. GrafPtr        savePort;
  229. OSErr        theErr;
  230. ElemPtr        theElem;
  231.  
  232.     GetPort( &savePort );
  233.     SetPort( Doc_GetWindow( theDoc ) );
  234.  
  235.     HLock ((Handle) thePict);
  236.     theRect = (**(thePict)).picFrame;
  237.     
  238.     thePt.h += theRect.left - (theRect.right - theRect.left)/2;
  239.     thePt.v += theRect.top - (theRect.bottom - theRect.top)/2;
  240.  
  241.     theElem = Elem_New ((Handle) thePict, kPICTType, theRect, thePt);
  242.     ElemColl_AddElem (theDoc->contentColl, theElem);
  243.  
  244.     HUnlock ((Handle) thePict);
  245.  
  246.     Elem_SetVisible (theElem, true);
  247.     
  248.     // draw the item, unselected.
  249.  
  250.     Doc_SetDirty( theDoc, true );
  251.     SetPort( savePort );
  252.     
  253.     return (theElem);
  254. }
  255.  
  256. //---------------------------------------------------------------------------
  257. // Doc_AddItemsFromScrap - 
  258.  
  259. void Doc_AddItemsFromScrap(
  260.     DocPtr        theDoc,
  261.     Handle        theScrap,
  262.     Point        origin )
  263. {
  264. PicHandle    aPicture;
  265. Ptr            offsetPtr;
  266. Point        location, sourceOrigin;
  267. OSErr        theErr;
  268. long        pictSize, pictCount, i;
  269. ElemPtr        elem;
  270.  
  271.     offsetPtr = *theScrap;
  272.     BlockMoveData( offsetPtr, (Ptr)&sourceOrigin, (long)sizeof(Point) );
  273.     offsetPtr += sizeof(Point);
  274.  
  275.     BlockMoveData( offsetPtr, (Ptr)&pictCount, (long)sizeof(long) );
  276.     offsetPtr += sizeof(long);
  277.  
  278.     Doc_SelectAllElements( theDoc, false );
  279.  
  280.     for (i=0; i<pictCount; ++i)
  281.     {
  282.         BlockMoveData( (Ptr)offsetPtr, (Ptr)&location, (long)sizeof(Point) );
  283.         offsetPtr += sizeof(Point);
  284.  
  285.         BlockMoveData( (Ptr)offsetPtr, (Ptr)&pictSize, (long)sizeof(long) );
  286.         offsetPtr += sizeof(long);
  287.  
  288.         // New location is the new origin + the relative offset
  289.         // of the item
  290.         location.h = origin.h + (location.h - sourceOrigin.h);
  291.         location.v = origin.v + (location.v - sourceOrigin.v);
  292.  
  293.         aPicture = (PicHandle)NewHandle( pictSize );
  294.         theErr = MemError();
  295.         if (theErr == noErr)
  296.         {
  297.             BlockMoveData( (Ptr)offsetPtr, *aPicture, pictSize );
  298.             offsetPtr += pictSize;
  299.  
  300.             // Adjust the location
  301.             elem = Doc_AddItemPict( theDoc, aPicture, location );
  302.             Elem_SetSelected (elem, true);
  303.         }
  304.     }
  305. }
  306.  
  307. //---------------------------------------------------------------------------
  308. // Doc_SelectionExists - if any item is selected, return true.
  309.  
  310. Boolean Doc_SelectionExists(
  311.     DocPtr    theDoc )
  312. {
  313. short        count, i;
  314. ElemPtr        elem;
  315. Boolean        retVal = false;
  316.  
  317.     count = ElemColl_GetCount (theDoc->contentColl);
  318.     
  319.     for (i=1; i <= count; i++)
  320.     {
  321.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  322.         if (Elem_GetSelected (elem))
  323.         {
  324.             retVal = true;
  325.             break;
  326.         }
  327.     }
  328.  
  329.     return retVal;
  330. }
  331.  
  332.  
  333. //---------------------------------------------------------------------------
  334. // Doc_GetSelectedFrameCount
  335.  
  336. short Doc_GetSelectedFrameCount(
  337.     DocPtr    theDoc )
  338. {
  339. short        count, i;
  340. short        selectedCount = 0;
  341. ElemPtr        elem;
  342.  
  343.     count = ElemColl_GetCount (theDoc->contentColl);
  344.     
  345.     for (i=1; i <= count; i++)
  346.     {
  347.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  348.         if (Elem_GetSelected (elem) && (Elem_GetType (elem) == kFrameElemType))
  349.         {
  350.             ++selectedCount;
  351.         }
  352.     }
  353.  
  354.     return selectedCount;
  355. }
  356.  
  357.  
  358. //---------------------------------------------------------------------------
  359. // Set the select flag on all the items in the window's document to bSelect.
  360. // Also inval the rects of the items so they are redrawn.
  361. // Origin is not important and may be set to 0, 0 upon exit.
  362.  
  363. void Doc_SelectAllElements(
  364.     DocPtr        theDoc,
  365.     Boolean        bSelect )
  366. {
  367. short        count, i;
  368. ElemPtr        elem;
  369.  
  370.     count = ElemColl_GetCount (theDoc->contentColl);
  371.     
  372.     for (i=1; i <= count; i++)
  373.     {
  374.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  375.         if (Elem_GetSelected (elem) != bSelect)
  376.         {
  377.             Elem_SetSelected (elem, bSelect);
  378.             
  379.         }
  380.     }
  381.     
  382.     ElemColl_ClipElements(theDoc->contentColl, NULL);
  383.  
  384. }
  385.  
  386.  
  387. //---------------------------------------------------------------------------
  388. // deletes all items that are selected from the window's document.
  389. // Also inval the rects of the items so they are redrawn.
  390. // Origin is not important and will be set to 0, 0 upon exit.
  391.  
  392. void Doc_DeleteElements(
  393.     DocPtr    theDoc, ElemListPtr    selectionList )
  394. {
  395. Point        saveOrigin;
  396. long        i;
  397. short        count;
  398. ElemPtr        elem;
  399. GrafPtr        savePort;
  400.  
  401.     GetPort (&savePort);
  402.     SetPort (Doc_GetWindow(theDoc));
  403.  
  404.     // move the coordinate system according to the scroll bars.
  405.     GetOrigin( &saveOrigin );
  406.     Doc_SetGrafOrigin( theDoc );
  407.  
  408.     count = ElemList_GetCount (selectionList);
  409.     
  410.     for (i=count; i >= 1; i--)
  411.     {
  412.         elem = ElemList_GetNthElem (selectionList, i);
  413.         ElemColl_RemoveElem (theDoc->contentColl, elem);
  414.     }
  415.     
  416.     // set the coordinate system back.
  417.     SetOrigin( saveOrigin.h, saveOrigin.v );
  418.     SetPort (savePort);
  419.     
  420. }
  421.  
  422.  
  423. //---------------------------------------------------------------------------
  424. // deletes all items that are selected from the window's document.
  425. // Also inval the rects of the items so they are redrawn.
  426. // Origin is not important and will be set to 0, 0 upon exit.
  427.  
  428. void Doc_DeleteCurrentSelection(
  429.     DocPtr    theDoc )
  430. {
  431. Point        saveOrigin;
  432. long        i;
  433. short        count;
  434. ElemPtr        elem;
  435. GrafPtr        savePort;
  436.  
  437.     GetPort (&savePort);
  438.     SetPort (Doc_GetWindow(theDoc));
  439.  
  440.     // move the coordinate system according to the scroll bars.
  441.     GetOrigin( &saveOrigin );
  442.     Doc_SetGrafOrigin( theDoc );
  443.  
  444.     count = ElemColl_GetCount (theDoc->contentColl);
  445.     
  446.     for (i=count; i >= 1; i--)
  447.     {
  448.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  449.  
  450.         if (Elem_GetSelected (elem))
  451.         {
  452.             ElemColl_RemoveElem (theDoc->contentColl, elem);
  453.         }
  454.     }
  455.     
  456.     // set the coordinate system back.
  457.     SetOrigin( saveOrigin.h, saveOrigin.v );
  458.     SetPort (savePort);
  459.     
  460. }
  461.  
  462. //---------------------------------------------------------------------------
  463. // Move all the selected items by offsetH pixels to the right and offsetV pixels down.
  464. // Also inval the rects of the items original and final location so they are redrawn.
  465. // Origin is not important and will be set to 0, 0 upon exit.
  466.  
  467. void Doc_MoveSelection(
  468.     DocPtr    theDoc,
  469.     short    offsetH,
  470.     short    offsetV )
  471. {
  472. Point        location;
  473. Point        saveOrigin;
  474. long        i;
  475. short        count;
  476. ElemPtr        elem;
  477.  
  478.     // move the coordinate system according to the scroll bars.
  479.     GetOrigin( &saveOrigin );
  480.     Doc_SetGrafOrigin( theDoc );
  481.  
  482.     count = ElemColl_GetCount (theDoc->contentColl);
  483.     
  484.     for (i=count; i >= 1; i--)
  485.     {
  486.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  487.  
  488.         if (Elem_GetSelected (elem))
  489.         {
  490.             Elem_GetLocation (elem, &location);
  491.             location.v += offsetV;
  492.             location.h += offsetH;
  493.             Elem_SetLocation (elem, location);
  494.             Elem_UpdateCAVisFrame(elem);
  495.         
  496.         }
  497.         
  498.     }
  499.     // set the coordinate system back.
  500.     SetOrigin( saveOrigin.h, saveOrigin.v );
  501. }
  502.  
  503. //---------------------------------------------------------------------------
  504. // return the bounding box of all the selected items in document coords.
  505. // This routine should not be called unless there is at least one item selected.
  506. // It will return an empty rect in this case.
  507.  
  508. void Doc_CalcSelectionBounds(
  509.     DocPtr    theDoc,
  510.     Rect    *boundsRect )
  511. {
  512. Rect        theRect;
  513. long        i;
  514. short        count;
  515. ElemPtr        elem;
  516.  
  517.     // loop through all the items
  518.     // if the item is selected, add it to the boundsRect.
  519.     SetRect( boundsRect, 0, 0, 0, 0 );
  520.     
  521.     count = ElemColl_GetCount (theDoc->contentColl);
  522.     
  523.     for (i=1; i <= count; i++)
  524.     {
  525.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  526.         
  527.         if (Elem_GetSelected (elem))
  528.         {
  529.             Elem_GetLocatedRect (elem, &theRect);
  530.             
  531.             if (EmptyRect (boundsRect))
  532.                 *boundsRect = theRect;
  533.             else
  534.                 UnionRect( boundsRect, &theRect, boundsRect );
  535.         }
  536.         
  537.     }
  538.  
  539. }
  540.  
  541. //---------------------------------------------------------------------------
  542. // return the bounding box of all items, in document coords.
  543.  
  544. void Doc_CalcContentBounds(
  545.     DocPtr    theDoc,
  546.     Rect    *boundsRect )
  547. {
  548. Rect        theRect;
  549. long        i;
  550. short        count;
  551. ElemPtr        elem;
  552.  
  553.     // loop through all the items
  554.     // if the item is selected, add it to the boundsRect.
  555.     SetRect( boundsRect, 0, 0, 0, 0 );
  556.     
  557.     count = ElemColl_GetCount (theDoc->contentColl);
  558.     
  559.     for (i=1; i <= count; i++)
  560.     {
  561.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  562.         
  563.         Elem_GetLocatedRect (elem, &theRect);
  564.         
  565.         if (EmptyRect (boundsRect))
  566.             *boundsRect = theRect;
  567.         else
  568.             UnionRect( boundsRect, &theRect, boundsRect );
  569.         
  570.     }
  571.  
  572. }
  573.  
  574.  
  575.  
  576. //---------------------------------------------------------------------------
  577. // Return the region of all the selected items in document coords.
  578. // This routine should not be called unless there is at least one item selected.
  579. // It will return an empty rect in this case.
  580.  
  581. void Doc_CalcSelectionRgn(
  582.     DocPtr        theDoc,
  583.     RgnHandle    theRgn )
  584. {
  585. RgnHandle        itemRgn;
  586. Rect            itemRect;
  587. long            i;
  588. long            count;
  589. ElemPtr            elem;
  590.  
  591.     SetRect( &itemRect, 0, 0, 0, 0 );
  592.     RectRgn( theRgn, &itemRect );
  593.  
  594.     itemRgn = NewRgn();
  595.  
  596.     count = ElemColl_GetCount (theDoc->contentColl);
  597.     
  598.     for (i=1; i <= count; i++)
  599.     {
  600.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  601.         
  602.         if (Elem_GetSelected (elem))
  603.         {
  604.             Elem_GetLocatedRect (elem, &itemRect);
  605.             RectRgn( itemRgn, &itemRect );
  606.             UnionRgn( theRgn, itemRgn, theRgn );
  607.         }
  608.         
  609.     }
  610.  
  611.     DisposeRgn (itemRgn);
  612.     
  613. }
  614.  
  615.  
  616. //---------------------------------------------------------------------------
  617. // Return the region of all the selected items in document coords.
  618. // This routine should not be called unless there is at least one item selected.
  619. // It will return an empty rect in this case.
  620.  
  621. void Doc_CalcContentElemRgn(
  622.     DocPtr        theDoc,
  623.     RgnHandle    theRgn )
  624. {
  625. RgnHandle    itemRgn;
  626. Rect        itemRect;
  627. short        i, count;
  628. ElemPtr        elem;
  629.  
  630.     SetRect( &itemRect, 0, 0, 0, 0 );
  631.     RectRgn( theRgn, &itemRect );
  632.  
  633.     itemRgn = NewRgn();
  634.  
  635.     count = ElemColl_GetCount (theDoc->contentColl);
  636.     
  637.     for (i=1; i <= count; i++)
  638.     {
  639.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  640.         
  641.         Elem_GetLocatedRect (elem, &itemRect);
  642.         RectRgn( itemRgn, &itemRect );
  643.         UnionRgn( theRgn, itemRgn, theRgn );
  644.                 
  645.     }
  646.     
  647.     DisposeRgn( itemRgn );
  648.  
  649. }
  650.  
  651.  
  652. //---------------------------------------------------------------------------
  653.  
  654. Handle Doc_CreateScrapFromSelection(
  655.     DocPtr    theDoc )
  656. {
  657. Handle        scrapData;
  658. Ptr            scrapOffset;
  659. Rect        boundsRect;
  660. Point        origin;
  661. Point        location;
  662. OSErr        theErr;
  663. long        itemCount, scrapSize, pictSize, i;
  664. ElemPtr        elem;
  665. short        pictElemCount;
  666.  
  667.  
  668.     itemCount = 0L;
  669.     scrapSize = 0L;
  670.  
  671.     Doc_CalcSelectionBounds( theDoc, &boundsRect );
  672.     origin.h = boundsRect.left;
  673.     origin.v = boundsRect.top;
  674.  
  675.     pictElemCount = ElemColl_GetCountOfType (theDoc->contentColl, kPICTType);
  676.     
  677.     for (i=1; i<=pictElemCount; i++)
  678.     {
  679.     
  680.         elem = ElemColl_GetNthElemOfType (theDoc->contentColl, i, kPICTType);
  681.         
  682.         if (Elem_GetSelected (elem))
  683.         {
  684.             ++itemCount;
  685.             scrapSize += GetHandleSize( (Handle) elem->elemData );
  686.  
  687.         }
  688.     }
  689.  
  690.     scrapSize +=
  691.         sizeof(Point) + sizeof(long)
  692.         + (itemCount * (sizeof(Point) + sizeof(long)));
  693.     scrapData = NewHandle( scrapSize );
  694.     theErr = MemError();
  695.     if (theErr != noErr)
  696.         return nil;
  697.  
  698.     scrapOffset = *scrapData;
  699.  
  700.     BlockMoveData( &origin, scrapOffset, (long)sizeof(Point) );
  701.     scrapOffset += sizeof(Point);
  702.  
  703.     BlockMoveData( &itemCount, scrapOffset, (long)sizeof(long) );
  704.     scrapOffset += sizeof(long);
  705.      
  706.     pictElemCount = ElemColl_GetCountOfType (theDoc->contentColl, kPICTType);
  707.     
  708.     for (i=1; i<=pictElemCount; i++)
  709.     {
  710.     
  711.         elem = ElemColl_GetNthElemOfType (theDoc->contentColl, i, kPICTType);
  712.         
  713.         if (Elem_GetSelected (elem))
  714.         {
  715.             pictSize = GetHandleSize( (Handle)elem->elemData );
  716.             Elem_GetLocation (elem, &location);
  717.             BlockMoveData(
  718.                 (Ptr)&location,
  719.                 (Ptr)scrapOffset, (long)sizeof(Point) );
  720.             scrapOffset += sizeof(Point);
  721.  
  722.             BlockMoveData(
  723.                 (Ptr)&pictSize, (Ptr) scrapOffset,
  724.                 (long)sizeof(long) );
  725.             scrapOffset += sizeof(long);
  726.  
  727.  
  728.         }
  729.     }
  730.  
  731.     // loop through all the items, drawing the selected ones.
  732.     // if the item is selected, draw it.
  733.  
  734.     return scrapData;
  735. }
  736.  
  737.  
  738. //---------------------------------------------------------------------------
  739. // return a picture containing all the selected items.
  740. // This routine should not be called unless there is at least one item selected.
  741. // It will return nil in this case.
  742.  
  743. PicHandle Doc_CreateSelectionPicture(
  744.     DocPtr    theDoc )
  745. {
  746. Rect            boundsRect;
  747. Point            saveOrigin;
  748. PicHandle        thePicture;
  749. short            count, i;
  750. ElemPtr            elem;
  751.  
  752.     Doc_CalcSelectionBounds( theDoc, &boundsRect );
  753.     if (EmptyRect( &boundsRect ))
  754.         return nil;
  755.  
  756.     // move the coordinate system according to the scroll bars.
  757.     GetOrigin( &saveOrigin );
  758.     Doc_SetGrafOrigin( theDoc );
  759.  
  760.     thePicture = OpenPicture( &boundsRect );
  761.  
  762.     // loop through all the items, drawing the selected ones.
  763.  
  764.     count = ElemColl_GetCount (theDoc->contentColl);
  765.     for (i=1; i <= count; i++)
  766.     {
  767.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  768.         
  769.         if (Elem_GetSelected (elem))
  770.         {
  771.             Elem_Draw (elem, false);
  772.         }
  773.     }
  774.  
  775.     ClosePicture();
  776.  
  777.     // set the coordinate system back.
  778.     SetOrigin( saveOrigin.h, saveOrigin.v );
  779.  
  780.     return thePicture;
  781. }
  782.  
  783. //---------------------------------------------------------------------------
  784. // save the current state of the document in undoData.
  785.  
  786. void Doc_SaveUndo(
  787.     DocPtr    theDoc )
  788. {
  789. #pragma unused (theDoc)
  790.  
  791. #if 0
  792. OSErr    theErr;
  793.  
  794.     // if the flag was set to save on the next operation...
  795.     if (theDoc->bUndoNext)
  796.     {
  797.         if (undoData != nil)
  798.         {
  799.             DisposeHandle( undoData );
  800.             undoData = nil;
  801.         }
  802.  
  803.         undoData = (**theDoc->TEH).hText;
  804.         theErr = HandToHand( &undoData );
  805.         if (theErr != noErr)
  806.             undoData = nil;        // give up on the undo.
  807.  
  808.         theDoc->undoSelStart = (**theDoc->TEH).selStart;
  809.         theDoc->undoSelEnd = (**theDoc->TEH).selEnd;
  810.     }
  811. #endif
  812. }
  813.  
  814. //---------------------------------------------------------------------------
  815. // restore the state of the document from undoData.
  816.  
  817. void Doc_RestoreUndo(
  818.     DocPtr    theDoc )
  819. {
  820. #pragma unused (theDoc)
  821.  
  822. #if 0
  823. Handle    theHandle;
  824. OSErr    theErr;
  825. short    selStartTemp, selEndTemp;
  826.  
  827.     if (undoData != nil)
  828.     {
  829.         // set the text
  830.         theHandle = (**theDoc->TEH).hText;
  831.         theErr = HandToHand( &theHandle );    // save the current text
  832.         if (theErr != noErr)
  833.             undoData = nil;
  834.         else
  835.         {
  836.             // save the current selection
  837.             selStartTemp = (**theDoc->TEH).selStart;
  838.             selEndTemp = (**theDoc->TEH).selEnd;
  839.  
  840.             // restore the undo text
  841.             doSetText( undoData, theDoc->TEH, theDoc );
  842.             doSetSelect( theDoc->undoSelStart, theDoc->undoSelEnd, theDoc->TEH, false, theDoc );
  843.  
  844.             theDoc->undoSelStart = selStartTemp;
  845.             theDoc->undoSelEnd = selEndTemp;
  846.         }
  847.  
  848.         // store the current text into the undo text
  849.         undoData = theHandle;
  850.     }
  851. #endif
  852. }
  853.  
  854.  
  855. //---------------------------------------------------------------------------
  856. // dispose any memory used by undoData.
  857.  
  858. void Doc_DisposeUndo(
  859.     DocPtr    theDoc )
  860. {
  861. #pragma unused (theDoc)
  862.  
  863. #if 0
  864.     if (undoData != nil)
  865.     {
  866.         DisposeHandle( undoData );
  867.         undoData = nil;
  868.     }
  869. #endif
  870. }
  871.  
  872. //---------------------------------------------------------------------------
  873. // return the window that owns this document.
  874.  
  875. WindowPtr Doc_GetWindow(
  876.     DocPtr    theDoc )
  877. {
  878. WindowPtr    curWindow;
  879.  
  880.     curWindow = FrontWindow();
  881.     while ((curWindow != nil) && ((DocPtr)GetWRefCon( curWindow ) != theDoc))
  882.         curWindow = (WindowPtr)(((WindowPeek)curWindow)->nextWindow);
  883.  
  884.     return curWindow;
  885. }
  886.  
  887. //---------------------------------------------------------------------------
  888.  
  889. void Doc_Draw(
  890.     DocPtr    theDoc )
  891. {
  892. Rect        theRect;
  893. WindowPtr    theWindow;
  894. long        i;
  895. short        count;
  896. ElemPtr        elem;
  897.  
  898.     theWindow = Doc_GetWindow( theDoc );
  899.  
  900.     count = ElemColl_GetCount (theDoc->contentColl);
  901.     
  902.     // draw the content area here. Back to front
  903.  
  904.     for (i=1; i <= count; i++)
  905.     {
  906.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  907.         Elem_GetDisplayRect (elem, &theRect);
  908.         
  909.         if (RectInRgn( &theRect, theWindow->clipRgn ))
  910.             Elem_Draw (elem, true);
  911.     }
  912.  
  913. }
  914.  
  915. //---------------------------------------------------------------------------
  916. // read theWindow's document data from the existing file theDoc->fileRefNum.
  917.  
  918. OSErr Doc_ReadFile(
  919.     DocPtr    theDoc )
  920. {
  921. Ptr            bufPtr;
  922. OSErr        theErr;
  923. fileHeader    theFileHeader;
  924. WindowPtr    theWindow;
  925. long        length, i;
  926. IOStream    ioStream;
  927. ElemPtr        elem;
  928.  
  929.     ioStream.type = fileStream;
  930.     ioStream.theDoc = theDoc;
  931.     ioStream.fileRef = theDoc->fileRefNum;
  932.     
  933.     theErr = noErr;
  934.     bSetCursorWatch();
  935.  
  936.     theErr = SetFPos( theDoc->fileRefNum, fsFromStart, 0L );
  937.  
  938. #ifdef USE_CALIB
  939.  
  940.     if (gCALibExists)
  941.     {
  942.         FInfo    finderInfo;
  943.  
  944.         FSpGetFInfo( &(theDoc->fileSpec), &finderInfo );
  945.         if (finderInfo.fdType == kContainerFileType)
  946.         {
  947.             // For doc's stored using the Bento Model, we need to
  948.             // open now.  Close the file so CAOpenDocument forsure can read it.
  949.             theErr = FSClose( theDoc->fileRefNum );
  950.             theDoc->storageModel = kBentoStorageModel;
  951.  
  952.             // The CADocument's current kind is set to the first content value
  953.             // by default, stream offset == 0 also by default.
  954.             theDoc->partDocRef = CAOpenDocument( &(theDoc->fileSpec), NULL, 0, 0);
  955.         }
  956.         else
  957.         {
  958.             theDoc->storageModel = kNativeStorageModel;
  959.         }
  960.     }
  961.  
  962. #endif
  963.  
  964.     if (theErr == noErr)
  965.     {
  966.         // read in the header.
  967.         length = sizeof(fileHeader);
  968.         bufPtr = (Ptr)&theFileHeader;
  969.  
  970. #ifdef USE_CALIB
  971.         if (gCALibExists)
  972.             theErr = CAUtil_ReadWrapper (&ioStream, bufPtr, &length);
  973.         else
  974.             theErr = FSRead( theDoc->fileRefNum, &length, bufPtr );
  975. #else
  976.         theErr = FSRead( theDoc->fileRefNum, &length, bufPtr );
  977. #endif
  978.  
  979.     }
  980.  
  981.     if (theErr == noErr)
  982.     {
  983.         if (theFileHeader.version != kFileVersion)
  984.             theErr = paramErr;
  985.     }
  986.     
  987.     if (theErr == noErr)
  988.     {
  989.         // get the header data
  990.         theDoc->hPrint = (THPrint)NewHandle( (long)sizeof(TPrint) );
  991.         theErr = MemError();
  992.     }
  993.  
  994.     if (theErr == noErr)
  995.     {
  996.         BlockMoveData( &theFileHeader.printRecord, *(theDoc->hPrint), (long)sizeof(TPrint) );
  997.  
  998.         // 8 by 10 inches at 72dpi
  999.         PrOpen();
  1000.         SetRect( &theDoc->documentRect, 0, 0, 8*72, 10*72 );
  1001.         if (PrError() == noErr)
  1002.             if (!checkPrintHandle( &theDoc->hPrint ))
  1003.                 // the printable area of the paper
  1004.                 theDoc->documentRect = (**theDoc->hPrint).prInfo.rPage;
  1005.  
  1006.         PrClose();
  1007.     }
  1008.  
  1009.     theWindow = Doc_GetWindow( theDoc );
  1010.  
  1011.     if (theWindow)
  1012.     {
  1013.         MoveWindow(
  1014.             theWindow, theFileHeader.windowRect.left,
  1015.             theFileHeader.windowRect.top, false );
  1016.         SizeWindow(
  1017.             theWindow, theFileHeader.windowRect.right - theFileHeader.windowRect.left, 
  1018.             theFileHeader.windowRect.bottom - theFileHeader.windowRect.top, true );
  1019.  
  1020.         theDoc->documentRect = theFileHeader.documentRect;
  1021.  
  1022.         // make sure this window is visible on screen
  1023.         Win_CheckWindowPosition( theWindow );
  1024.  
  1025.         SetControlValue( theDoc->hScrollBar, theFileHeader.hScrollValue );
  1026.         SetControlValue( theDoc->vScrollBar, theFileHeader.vScrollValue );
  1027.  
  1028.         theDoc->insertionPoint = theFileHeader.insertionPoint;
  1029.         
  1030.     }
  1031.  
  1032.     // read in the itemArray.
  1033.     if (theErr == noErr)
  1034.     {
  1035.     
  1036.         for (i=0; i<theFileHeader.elemCount; ++i)
  1037.         {
  1038.             elem = Elem_Read(&ioStream);
  1039.             ElemColl_AddElem (theDoc->contentColl, elem);
  1040.         }
  1041.     
  1042.     }
  1043.     
  1044. #ifdef USE_CALIB
  1045.  
  1046.     if (gCALibExists)
  1047.     {
  1048.     
  1049.         if (theDoc->storageModel == kNativeStorageModel)
  1050.         {
  1051.             long    offset;
  1052.             CASize    length;
  1053.             long    numBytes;
  1054.  
  1055.             // $$$$$ need to perform error handling here…
  1056.             offset = 0L;
  1057.             numBytes = sizeof(length);
  1058.             theErr = FSRead( theDoc->fileRefNum, &numBytes, (Ptr)&length );
  1059.  
  1060.             theErr = GetFPos( theDoc->fileRefNum, &offset);
  1061.             theErr = FSClose( theDoc->fileRefNum);
  1062.             
  1063.             theDoc->partDocRef = CAOpenDocument( &(theDoc->fileSpec),
  1064.                                                 NULL,
  1065.                                                 offset,
  1066.                                                 length);
  1067.  
  1068.             if (CAError())
  1069.                 ;        // handle the error
  1070.  
  1071.             FSpOpenDF( &theDoc->fileSpec, fsRdWrPerm, &theDoc->fileRefNum );
  1072.         }
  1073.         else
  1074.         {
  1075.             // Get back a refNum so other stuff doesn't break;
  1076.             theErr = FSpOpenDF( &theDoc->fileSpec, fsRdPerm, &theDoc->fileRefNum );
  1077.         }
  1078.         
  1079.     }
  1080. #endif
  1081.  
  1082.     SetCursor( &qd.arrow );
  1083.  
  1084.     return theErr;
  1085. }
  1086.  
  1087. //---------------------------------------------------------------------------
  1088. // write the document's data to the existing file theDoc->fileRefNum.
  1089.  
  1090. OSErr Doc_WriteFile(
  1091.     DocPtr    theDoc )
  1092. {
  1093. fileHeader    theFileHeader;
  1094. Ptr            bufPtr;
  1095. OSErr        theErr = noErr;
  1096. WindowPtr    theWindow;
  1097. long        length, i;
  1098. IOStream    ioStream;
  1099. short        count;
  1100. ElemPtr        elem;
  1101.  
  1102.     ioStream.type = fileStream;
  1103.     ioStream.theDoc = theDoc;
  1104.     ioStream.fileRef = theDoc->fileRefNum;
  1105.  
  1106. #ifdef USE_CALIB
  1107.  
  1108.     if (!gCALibExists)
  1109.         theErr = SetFPos( theDoc->fileRefNum, fsFromStart, 0L );
  1110.     else
  1111.     {
  1112.         if (theDoc->storageModel == kNativeStorageModel)
  1113.         {
  1114.             theErr = SetFPos( theDoc->fileRefNum, fsFromStart, 0L );
  1115.         }
  1116.         else
  1117.         {
  1118.             // Set the Bento stream offset back to 0
  1119.             CASetDocumentKind (theDoc->partDocRef, kCASampleKind);
  1120.             CASetOffset( theDoc->partDocRef, 0 );
  1121.         }
  1122.     }
  1123. #else
  1124.  
  1125.     theErr = SetFPos( theDoc->fileRefNum, fsFromStart, 0L );
  1126. #endif
  1127.  
  1128.     if (theErr != noErr)
  1129.         return theErr;
  1130.  
  1131.     bSetCursorWatch();
  1132.  
  1133.     // fill in the header.
  1134.     theFileHeader.version = kFileVersion;
  1135.     if (theDoc->hPrint != nil)
  1136.         BlockMoveData( *(theDoc->hPrint), &theFileHeader.printRecord, (long)sizeof(TPrint) );
  1137.     else
  1138.         blockErase( (Ptr)&theFileHeader.printRecord, (long)sizeof(TPrint) );
  1139.  
  1140.     theWindow = Doc_GetWindow( theDoc );
  1141.     if (theWindow != nil)
  1142.     {
  1143.         GrafPtr    savePort;
  1144.         
  1145.         GetPort (&savePort);
  1146.         SetPort (theWindow);
  1147.         
  1148.         theFileHeader.windowRect = theWindow->portRect;
  1149.         RectLocalToGlobal( &theFileHeader.windowRect );
  1150.         
  1151.         SetPort (savePort);
  1152.         
  1153.     }
  1154.     else
  1155.         SetRect( &theFileHeader.windowRect, 20, 20, 300, 400 );
  1156.  
  1157.     theFileHeader.documentRect = theDoc->documentRect;
  1158.     theFileHeader.hScrollValue = GetControlValue( theDoc->hScrollBar );
  1159.     theFileHeader.vScrollValue = GetControlValue( theDoc->vScrollBar );
  1160.     theFileHeader.elemCount = ElemColl_GetCount (theDoc->contentColl);;
  1161.     theFileHeader.insertionPoint = theDoc->insertionPoint;
  1162.  
  1163.     length = sizeof(fileHeader);
  1164.     bufPtr = (Ptr)&theFileHeader;
  1165.  
  1166. #ifdef USE_CALIB
  1167.     if (gCALibExists)
  1168.         theErr = CAUtil_WriteWrapper (&ioStream, bufPtr, &length);
  1169.     else
  1170.         theErr = FSWrite( theDoc->fileRefNum, &length, bufPtr );
  1171. #else
  1172.  
  1173.     theErr = FSWrite( theDoc->fileRefNum, &length, bufPtr );
  1174. #endif
  1175.  
  1176.     // write out the contents.
  1177.     if (theErr == noErr)
  1178.     {
  1179.         count = ElemColl_GetCount (theDoc->contentColl);
  1180.         for (i=1; i <= count; i++)
  1181.         {
  1182.  
  1183.             elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  1184.             Elem_Write (elem, &ioStream);
  1185.             
  1186.         }
  1187.     }
  1188.  
  1189. #ifdef USE_CALIB
  1190.  
  1191.  
  1192.     if (gCALibExists)
  1193.     {
  1194.         long    offset;
  1195.         CASize    length;
  1196.         long    numBytes;
  1197.         
  1198.         // write out each embedded frame's data
  1199.         
  1200.         if (theDoc->storageModel == kNativeStorageModel)
  1201.         {
  1202.             // Make room for the Container length
  1203.             offset = 0L;
  1204.             numBytes = sizeof(length);
  1205.             theErr = FSWrite (theDoc->fileRefNum, &numBytes, (Ptr) &length);
  1206.             theErr = GetFPos(theDoc->fileRefNum, &offset);
  1207.  
  1208.             theErr = FSClose (theDoc->fileRefNum);
  1209.             CASaveDocument( theDoc->partDocRef, &(theDoc->fileSpec), NULL , offset, &length);
  1210.             if (CAError())
  1211.                 ;        // handle the error
  1212.             theErr = FSpOpenDF( &theDoc->fileSpec, fsRdWrPerm, &theDoc->fileRefNum );
  1213.  
  1214.             // Write out the correct length now
  1215.             theErr = SetFPos( theDoc->fileRefNum, fsFromStart, offset - 4 );
  1216.             numBytes = sizeof(length);
  1217.             theErr = FSWrite( theDoc->fileRefNum, &numBytes, (Ptr) &length );
  1218.             theErr = SetFPos( theDoc->fileRefNum, fsFromLEOF, 0 );
  1219.         }
  1220.         else
  1221.         {
  1222.         CASize    dataLength;
  1223.  
  1224.             // Close the file so CASaveDocument can write to it
  1225.             if (theDoc->fileRefNum != 0)
  1226.                 theErr = FSClose( theDoc->fileRefNum );
  1227.  
  1228.             dataLength = 0L;
  1229.             //CASaveDocument( theDoc->partDocRef, 0, &dataLength, &(theDoc->fileSpec), NULL );
  1230.             
  1231.             // save the container document in place
  1232.             CASaveDocument( theDoc->partDocRef, &(theDoc->fileSpec), NULL, 0, &dataLength);
  1233.             if (CAError())
  1234.                 ;        // handle the error
  1235.  
  1236.  
  1237.             // Get back a refNum so other stuff doesn't break
  1238.             theErr = FSpOpenDF( &(theDoc->fileSpec), fsRdPerm, &theDoc->fileRefNum );
  1239.         }
  1240.     }
  1241. #endif
  1242.  
  1243.     // set the end of the file (in case it was larger).
  1244.     //if (theErr = SetEOF(theDoc->fileRefNum, sizeof(fileHeader)+length))
  1245.     //    return(theErr);
  1246.     SetCursor( &qd.arrow );
  1247.  
  1248.     return theErr;
  1249. }
  1250.  
  1251. //---------------------------------------------------------------------------
  1252. // Save theWindow's data in a new file after asking the user to name the file.
  1253.  
  1254. OSErr Doc_SaveAs(
  1255.     DocPtr    theDoc )
  1256. {
  1257. Str255                thePrompt, theName;
  1258. StandardFileReply    theReply;
  1259. OSErr                theErr;
  1260. Point                thePt;
  1261. WindowPtr            theWindow;
  1262.  
  1263.     theErr = noErr;
  1264.  
  1265.     theWindow = Doc_GetWindow( theDoc );
  1266.     if (theWindow != nil)
  1267.         GetWTitle( theWindow, theName );
  1268.     else
  1269.         theName[0] = '\0';
  1270.  
  1271. #ifdef USE_CALIB
  1272.  
  1273.     if (gCALibExists)
  1274.     {
  1275.         short    storageModel;
  1276.  
  1277.         // CASample will pose a custom dialog which has a radio button
  1278.         // to specify Native or Bento storage.
  1279.         thePt.h = thePt.v = -1;
  1280.         storageModel = theDoc->storageModel;
  1281.         GetIndString( thePrompt, kStrings, itSavePrompt );
  1282.         
  1283.         if (!CARequestModalFocus( theWindow))
  1284.             return kCASErrCALib;
  1285.             
  1286.         CustomPutFile(
  1287.             thePrompt, theName, &theReply, kCASaveFileDialog, thePt, gDlgHookYDUPP, 
  1288.             gWindowEventFilterYDUPP, nil, nil, (short*) &storageModel );
  1289.  
  1290.         CARelinquishModalFocus( theWindow );
  1291.  
  1292.         theDoc->storageModel = storageModel;
  1293.     }
  1294.     else
  1295.     {
  1296.         // ask the user to name the file.
  1297.         // {-1, -1} centers PutFile on the screen.
  1298.         thePt.h = thePt.v = -1;
  1299.         GetIndString( thePrompt, kStrings, itSavePrompt );
  1300.         
  1301.         CustomPutFile(
  1302.             thePrompt, theName, &theReply, 0, thePt, nil, 
  1303.             gWindowEventFilterYDUPP, nil, nil, nil );
  1304.  
  1305.     }
  1306. #else
  1307.  
  1308.     // ask the user to name the file.
  1309.     // {-1, -1} centers PutFile on the screen.
  1310.     thePt.h = thePt.v = -1;
  1311.     GetIndString( thePrompt, kStrings, itSavePrompt );
  1312.     CustomPutFile(
  1313.         thePrompt, theName, &theReply, 0, thePt, nil, 
  1314.         gWindowEventFilterYDUPP, nil, nil, nil );
  1315. #endif
  1316.  
  1317.     // if the reply was not good, the user canceled.
  1318.     if (!theReply.sfGood)
  1319.         return userCanceledErr;
  1320.  
  1321.     // if we're not replacing an existing file, create a new file.
  1322.     if (!theReply.sfReplacing)
  1323.     {
  1324.         theErr =
  1325.             FSpCreate(
  1326.                 &theReply.sfFile, kOurFileCreator,
  1327.                 kOurFileType, theReply.sfScript );
  1328.     }
  1329.  
  1330.     theDoc->fileSpec = theReply.sfFile;
  1331.  
  1332.     // if the document was open in another file, close it.
  1333.     if (theErr == noErr)
  1334.         if (theDoc->fileRefNum != 0)
  1335.             theErr = FSClose( theDoc->fileRefNum );
  1336.  
  1337.     // open the new file.
  1338.     if (theErr == noErr)
  1339.         theErr = FSpOpenDF( &theReply.sfFile, fsRdWrPerm, &theDoc->fileRefNum );
  1340.  
  1341.     // write the doc data.
  1342.     if (theErr == noErr)
  1343.         theErr = Doc_WriteFile( theDoc );
  1344.  
  1345. #ifdef USE_CALIB
  1346.     if (gCALibExists)
  1347.     {
  1348.         // Change the file type appropriatly
  1349.         FInfo    finderInfo;
  1350.         OSType    fileType;
  1351.             
  1352.         fileType = (theDoc->storageModel == kBentoStorageModel) ? kContainerFileType
  1353.                             : kOurFileType;
  1354.         FSpGetFInfo( &theReply.sfFile, &finderInfo );
  1355.         finderInfo.fdType = fileType;
  1356.         FSpSetFInfo( &theReply.sfFile, &finderInfo );
  1357.  
  1358.     }
  1359. #endif
  1360.  
  1361.     if (theErr != noErr)
  1362.         DEBUGSTR( "\pDoc_SaveAs: we have an error" );
  1363.  
  1364.     // change the window title and clear the changed flag.
  1365.     if (theErr == noErr)
  1366.     {
  1367.         if (theWindow != nil)
  1368.             SetWTitle( theWindow, theReply.sfFile.name );
  1369.         Doc_SetDirty( theDoc, false );
  1370.     }
  1371.  
  1372.     return theErr;
  1373. }
  1374.  
  1375. //---------------------------------------------------------------------------
  1376. // Save theWindow's data in a file asking the user to name the file if necessary.
  1377.  
  1378. OSErr Doc_Save(
  1379.     DocPtr    theDoc )
  1380. {
  1381. OSErr    theErr;
  1382.  
  1383.     // if the file has no refNum, then we need to name it
  1384.     theErr = noErr;
  1385.     if (theDoc->fileRefNum == 0)
  1386.         theErr = Doc_SaveAs( theDoc );
  1387.     else
  1388.     {
  1389.         theErr = Doc_WriteFile( theDoc );
  1390.         if (theErr == noErr)
  1391.             Doc_SetDirty( theDoc, false );
  1392.     }
  1393.  
  1394.  
  1395.     return theErr;
  1396. }
  1397.  
  1398. //---------------------------------------------------------------------------
  1399. // Doc_New - does any initialization that the doc and it's window might need.
  1400.  
  1401. OSErr Doc_New( void )
  1402. {
  1403. DocPtr            theDoc;
  1404. GrafPtr            savePort;
  1405. WindowPtr        theWindow;
  1406. Rect            windowRect;
  1407. OSErr            theErr;
  1408. FSSpec            fileSpec;
  1409.  
  1410.     theErr = noErr;
  1411.  
  1412.     theDoc = (DocPtr)NewPtrClear( (long)sizeof(DocRecord) );
  1413.     if (theDoc != nil)
  1414.         Doc_InitData( theDoc );
  1415.     else
  1416.     {
  1417.         theErr = MemError();
  1418.         return theErr;
  1419.     }
  1420.  
  1421.     // create a new window
  1422.     SetRect( &windowRect, 10, GetMBarHeight() + 22, 300, 400 );
  1423.     OffsetRect( &windowRect, gWindowCount * 10, gWindowCount * 10 );
  1424.  
  1425.     GetPort( &savePort );
  1426.  
  1427.     // if the window failed to be created, get rid of the theDoc and return an error.
  1428.     theWindow = Win_New( nil, &windowRect );
  1429.     if (theWindow == nil)
  1430.     {
  1431.         DisposePtr( (Ptr)theDoc );
  1432.         return memFullErr;
  1433.     }
  1434.  
  1435.     // attach the theDoc to our window.
  1436.     SetWRefCon( theWindow, (long)theDoc );
  1437.  
  1438. #ifdef USE_CALIB
  1439.     sCopyStr ("\pUntitled", fileSpec.name);
  1440.     FindFolder(0, kDesktopFolderType, kDontCreateFolder,&(fileSpec.vRefNum),&(fileSpec.parID));
  1441.     MakeDatedUniqueFSSpec (&fileSpec);
  1442.     theDoc->fileSpec = fileSpec;
  1443.     SetWTitle( theWindow, fileSpec.name );
  1444.  
  1445. #else
  1446.     // set the window title.
  1447.     gWindowCount += 1;
  1448.     NumToString( gWindowCount, theStr );
  1449.     GetIndString( theName, kStrings, itUntitled );
  1450.     sParamStr( theName, theStr, nil, nil, nil, nil, nil, nil, nil, nil, nil );
  1451.     SetWTitle( theWindow, theName );
  1452. #endif
  1453.  
  1454.  
  1455.     SetPort( theWindow );
  1456.  
  1457.     // check the print handle and get the size of a page.
  1458.     // 8 by 10 inches at 72dpi
  1459.     SetRect( &theDoc->documentRect, 0, 0, 8*72, 10*72 );
  1460.     PrOpen();
  1461.     theErr = PrError();
  1462.     if (theErr == noErr)
  1463.     {
  1464.         if (theDoc->hPrint != nil)
  1465.             if (checkPrintHandle( &theDoc->hPrint ))
  1466.                 // the printable area of the paper
  1467.                 theDoc->documentRect = (**theDoc->hPrint).prInfo.rPage;
  1468.         PrClose();
  1469.     }
  1470.  
  1471.     // set up the scroll bars
  1472.     // (hScrollBarRect and vScrollBarRect have not been set yet, but it's OK).
  1473.     theDoc->hScrollBar =
  1474.         NewControl(
  1475.             theWindow, &theDoc->hScrollBarRect, "\p", true, 
  1476.             0, 0, 0, scrollBarProc, (long)theDoc );
  1477.     theDoc->vScrollBar =
  1478.         NewControl(
  1479.             theWindow, &theDoc->vScrollBarRect, "\p", true, 
  1480.             0, 0, 0, scrollBarProc, (long)theDoc );
  1481.  
  1482. #ifdef USE_CALIB
  1483.     if (gCALibExists)
  1484.         theErr = Doc_InstallCALibHandlers( theDoc, theWindow, true );
  1485. #endif
  1486.  
  1487.     // adjust the window rects and regions and the scroll bars.
  1488.     // adjust the size for zooming.
  1489.     Win_Adjust( theWindow );
  1490.     Win_AdjustStdState( theWindow );
  1491.  
  1492.     // now show the window.
  1493.     Win_ShowHide( theWindow, true );
  1494.     App_SetFrontDocWindow( theWindow );
  1495.  
  1496.     SetPort( savePort );
  1497.  
  1498. #ifdef USE_CALIB
  1499.     // install the drag handlers
  1500.     if (gCALibExists)
  1501.         theErr = Doc_InstallDragHandlers( theDoc, theWindow );
  1502. #endif
  1503.  
  1504.      App_LogOpenDocument (theDoc);
  1505.      
  1506.     return theErr;
  1507. }
  1508.  
  1509.  
  1510. //---------------------------------------------------------------------------
  1511. // Doc_Open - does any initialization that the doc and its window might need.
  1512.  
  1513. OSErr Doc_Open(
  1514.     FSSpec    *theSpec )
  1515. {
  1516. GrafPtr        savePort;
  1517. WindowPtr    theWindow;
  1518. OSErr        theErr;
  1519. DocPtr        theDoc;
  1520. Rect        windowRect;
  1521. short        i;
  1522. ElemPtr        elem;
  1523. short        count;
  1524.  
  1525.     theDoc = (DocPtr)NewPtrClear( (long)sizeof(DocRecord) );
  1526.     if (theDoc != nil)
  1527.         Doc_InitData( theDoc );
  1528.     else
  1529.     {
  1530.         theErr = MemError();
  1531.         return theErr;
  1532.     }
  1533.  
  1534.     theDoc->fileSpec = *theSpec;
  1535.  
  1536.  
  1537.     // open the data fork
  1538.     theErr = FSpOpenDF( theSpec, fsRdWrPerm, &theDoc->fileRefNum );
  1539.     if (theErr == noErr)
  1540.     {
  1541.         theDoc->fileLocked = false;
  1542.     }
  1543.     else if (theErr == permErr)
  1544.     {
  1545.         // open the data fork (read-only)
  1546.         theDoc->fileLocked = true;
  1547.         theErr = FSpOpenDF( theSpec, fsRdPerm, &theDoc->fileRefNum );
  1548.     }
  1549.     else
  1550.     {
  1551.         DisposePtr( (Ptr)theDoc );
  1552.         return theErr;
  1553.     }
  1554.  
  1555.     SetRect( &windowRect, 10, 10, 200, 200 );
  1556.     theWindow = Win_New( nil, &windowRect );
  1557.     if (theWindow == nil)
  1558.     {
  1559.         FSClose( theDoc->fileRefNum );
  1560.         DisposePtr( (Ptr)theDoc );
  1561.         return memFullErr;
  1562.     }
  1563.  
  1564.     // attach the theDoc to our window.
  1565.     SetWRefCon( theWindow, (long)theDoc );
  1566.  
  1567.     // set the window's title
  1568.     SetWTitle( theWindow, theSpec->name );
  1569.  
  1570.     GetPort( &savePort );
  1571.     SetPort( (GrafPtr)theWindow );
  1572.  
  1573.     // set up the scroll bars
  1574.     // (hScrollBarRect and vScrollBarRect have not been set yet, but it's OK).
  1575.     theDoc->hScrollBar =
  1576.         NewControl(
  1577.             theWindow, &theDoc->hScrollBarRect, "\p", true, 
  1578.             0, 0, 0, scrollBarProc, (long)theDoc );
  1579.     theDoc->vScrollBar =
  1580.         NewControl(
  1581.             theWindow, &theDoc->vScrollBarRect, "\p", true, 
  1582.             0, 0, 0, scrollBarProc, (long)theDoc );
  1583.  
  1584.     // read in the file data.
  1585.     // $$$$$ don't forget to deal with errors
  1586.     theErr = Doc_ReadFile( theDoc );
  1587.     if (theErr != noErr)
  1588.     {
  1589.         FSClose( theDoc->fileRefNum );
  1590.         DisposePtr( (Ptr)theDoc );
  1591.         SetPort( savePort );
  1592.         return theErr;
  1593.     }
  1594.  
  1595. #ifdef USE_CALIB
  1596.     if (gCALibExists)
  1597.         theErr = Doc_InstallCALibHandlers( theDoc, theWindow, false );
  1598. #endif
  1599.  
  1600.     // adjust the window rects and regions and the scroll bars.
  1601.     // adjust the size for zooming.
  1602.     Win_Adjust( theWindow );
  1603.     Win_AdjustStdState( theWindow );
  1604.  
  1605.     SetPort( savePort );
  1606.  
  1607. #ifdef USE_CALIB
  1608.  
  1609.     // install the drag handlers
  1610.     theErr = Doc_InstallDragHandlers( theDoc, theWindow );
  1611.  
  1612.     // Make all content elements visible
  1613.     count = ElemColl_GetCount (theDoc->contentColl);
  1614.     
  1615.     for (i=1; i<=count; ++i)
  1616.     {
  1617.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  1618.         Elem_SetVisible (elem, true);
  1619.     }
  1620.     
  1621. #endif
  1622.  
  1623.      App_LogOpenDocument (theDoc);
  1624.  
  1625.     
  1626.     return noErr;
  1627. }
  1628.  
  1629. //---------------------------------------------------------------------------
  1630. // Doc_Close - Frees the doc item list
  1631.  
  1632. void Doc_Close(
  1633.     DocPtr    theDoc )
  1634. {
  1635.  
  1636.     ElemColl_FreeAll (theDoc->contentColl);
  1637.     
  1638. #ifdef USE_CALIB
  1639.     if (gCALibExists)
  1640.         CACloseDocument( (CADocumentRef)theDoc->partDocRef );
  1641. #endif
  1642.  
  1643.     
  1644. }
  1645.  
  1646.  
  1647. //---------------------------------------------------------------------------
  1648. // Doc_InstallDragHandlers - install the drag handlers.
  1649.  
  1650. static OSErr Doc_InstallDragHandlers(
  1651.     DocPtr        theDoc,
  1652.     WindowPtr    theWindow )
  1653. {
  1654. OSErr    theErr;
  1655.  
  1656.     theErr = noErr;
  1657.  
  1658. #ifdef USE_CALIB
  1659.  
  1660.     if (gCALibExists)
  1661.     {
  1662.         // install the drag handlers on the window.
  1663.         if (hasDragMgr)
  1664.         {
  1665.             theErr = CAInstallTrackingHandler(    gDragTrackingHandlerUPP,
  1666.                                                 theWindow,
  1667.                                                 nil );
  1668.  
  1669.             theErr = CAInstallReceiveHandler(    gDragReceiveHandlerUPP,
  1670.                                                 theWindow,
  1671.                                                 nil );
  1672.         }
  1673.     }
  1674.     else
  1675.     {
  1676.         // install the drag handlers on the window.
  1677.         if (hasDragMgr)
  1678.         {
  1679.             theErr =
  1680.                 InstallTrackingHandler(
  1681.                     gDragTrackingHandlerUPP,
  1682.                     theWindow,
  1683.                     nil );
  1684.             if (theErr == noErr)
  1685.             {
  1686.                 theErr =
  1687.                     InstallReceiveHandler(
  1688.                         gDragReceiveHandlerUPP,
  1689.                         theWindow,
  1690.                         nil );
  1691.                 if (theErr != noErr)
  1692.                     RemoveTrackingHandler(
  1693.                         gDragTrackingHandlerUPP,
  1694.                         theWindow );
  1695.             }
  1696.         }
  1697.     }
  1698.  
  1699. #else
  1700.  
  1701.     // install the drag handlers on the window.
  1702.     if (hasDragMgr)
  1703.     {
  1704.         theErr =
  1705.             InstallTrackingHandler(
  1706.                 gDragTrackingHandlerUPP,
  1707.                 theWindow,
  1708.                 nil );
  1709.         if (theErr == noErr)
  1710.         {
  1711.             theErr =
  1712.                 InstallReceiveHandler(
  1713.                     gDragReceiveHandlerUPP,
  1714.                     theWindow,
  1715.                     nil );
  1716.             if (theErr != noErr)
  1717.                 RemoveTrackingHandler(
  1718.                     gDragTrackingHandlerUPP,
  1719.                     theWindow );
  1720.         }
  1721.     }
  1722. #endif
  1723.  
  1724.     return theErr;
  1725. }
  1726.  
  1727. //---------------------------------------------------------------------------
  1728. // Doc_InstallCALibHandlers - install the standard CALib callback handlers.
  1729.  
  1730. static OSErr Doc_InstallCALibHandlers(
  1731.     DocPtr        theDoc,
  1732.     WindowPtr    theWindow,
  1733.     Boolean        isNewDoc )
  1734. {
  1735. CADocumentRef    newDocRef;
  1736. OSErr            theErr;
  1737.  
  1738.     // partDocRef was set in Doc_ReadFile
  1739.     theErr = noErr;
  1740.  
  1741.     if (isNewDoc)
  1742.     {
  1743.         // Don't bind CADocument until save time
  1744.         newDocRef = CACreateDocument(NULL, NULL);
  1745.         theDoc->partDocRef = newDocRef;
  1746.         theDoc->storageModel = kNativeStorageModel;
  1747.  
  1748.     }
  1749.     else
  1750.         newDocRef = theDoc->partDocRef;
  1751.  
  1752.     CAInstallFocusNotification(
  1753.         App_CAFocusAcquiredProc, App_CAFocusLostProc, newDocRef );
  1754.     if (theErr = CAError())
  1755.         ;        // handle the error
  1756.  
  1757.     CARegisterRootWindow( theWindow, newDocRef);
  1758.     if (theErr = CAError())
  1759.         ;        // handle the error
  1760.  
  1761.     CAInstallWindowActivateHandler( App_CAWindowActivateHandler, newDocRef );
  1762.     if (theErr = CAError())
  1763.         ;        // handle the error
  1764.  
  1765.     CAInstallFrameShapeRequestHandler( App_CAFrameShapeRequestHandler, newDocRef );
  1766.     if (theErr = CAError())
  1767.         ;        // handle the error
  1768.  
  1769.  
  1770.     CAInstallBorderAdjuster( newDocRef, App_CAAdjustBorderHandler );
  1771.     if (theErr = CAError())
  1772.         ;        // handle the error
  1773.  
  1774.     return theErr;
  1775. }
  1776.  
  1777. //---------------------------------------------------------------------------
  1778. // Edit Menu Items
  1779. //---------------------------------------------------------------------------
  1780. // Doc_UndoMenu - undo the last operation.
  1781. // assume it's our window.
  1782.  
  1783. void Doc_UndoMenu(
  1784.     DocPtr    theDoc )
  1785. {
  1786.     // if there is no undoText or the file is locked, get out.
  1787.     if ((theDoc == nil) || (theDoc->undoData == nil) || theDoc->fileLocked)
  1788.         return;
  1789.  
  1790.     Doc_RestoreUndo( theDoc );
  1791.  
  1792.     Win_ShowSelection( Doc_GetWindow( theDoc ) );
  1793. }
  1794.  
  1795.  
  1796. #ifdef USE_CALIB
  1797. //---------------------------------------------------------------------------
  1798. // odcCutMenu - CALib version
  1799.  
  1800. void Doc_CutMenu(
  1801.     DocPtr    theDoc )
  1802. {
  1803. PicHandle    thePicture;
  1804.  
  1805.     Doc_CopyMenu(theDoc, true);
  1806.  
  1807.     // delete the selection.
  1808.     Doc_DeleteCurrentSelection( theDoc );
  1809.  
  1810. }
  1811.  
  1812. //---------------------------------------------------------------------------
  1813. // odcCutMenu - cut the selection from the document onto the clipboard.
  1814. // Assume it's our window and there is a selection.
  1815.  
  1816. #else 
  1817.  
  1818. void Doc_CutMenu(
  1819.     DocPtr    theDoc )
  1820. {
  1821.  OSErr        theErr;
  1822.  
  1823.     // if the file is locked, beep and get out.
  1824.     // $$$$$ the cut menu should be disabled if the file is locked, so
  1825.     // we should never get here.
  1826.     if (theDoc->fileLocked)
  1827.     {
  1828.         SysBeep(2);
  1829.         return;
  1830.     }
  1831.  
  1832.     Doc_SaveUndo( theDoc );
  1833.     Doc_SetDirty( theDoc, true );
  1834.  
  1835.     // create a picture from the selected items.
  1836.     thePicture = Doc_CreateSelectionPicture( theDoc );
  1837.     if (thePicture == nil)
  1838.         return;
  1839.  
  1840.     // clear the scrap.
  1841.     ZeroScrap();
  1842.  
  1843.     // put our picture on the scrap ($$$$$ ignore any errors?).
  1844.     HLock( (Handle)thePicture );
  1845.     theErr = PutScrap( GetHandleSize( (Handle)thePicture ), kPICTType, (Ptr)*thePicture );    // put resource on clipboard
  1846.  
  1847.     // get rid of the picture.
  1848.     KillPicture( thePicture );
  1849.  
  1850.     // delete the selection.
  1851.     Doc_DeleteCurrentSelection( theDoc );
  1852.  
  1853.     // make sure the selection is visible in the window.
  1854.     Win_ShowSelection( Doc_GetWindow( theDoc ) );
  1855. }
  1856. #endif
  1857.  
  1858.  
  1859.  
  1860. #if CALIB_SAVVY_DATA_TRANSFER
  1861.  
  1862. //---------------------------------------------------------------------------
  1863. // Doc_CopyMenu - CALib savvy version
  1864. //
  1865. // CA writes all scrap formats to the system scrap as usual.
  1866. // In order to faciltate transfer of a single embedded frame to other OpenDoc
  1867. //     documents the CA must add a scrap type of 'odcn' if only a single frame is selected.
  1868.  
  1869. void Doc_CopyMenu(
  1870.     DocPtr    theDoc, Boolean isCut )
  1871. {
  1872. PicHandle        pictHandle;
  1873. Handle            scrapHandle;
  1874. CASize            length;
  1875. CADocumentRef    clipDoc = NULL;
  1876. Handle            compositeHandle;
  1877. Ptr                bufferPtr;
  1878. long            dataLength;
  1879. OSErr            theErr;
  1880. Boolean            anyFramesSelected;
  1881. Handle            containerHandle = NULL;
  1882. Boolean            singleFrame = false;
  1883.  
  1884.     // Empty the system scrap
  1885.     ZeroScrap();
  1886.  
  1887.     anyFramesSelected = (Doc_GetSelectedFrameCount (theDoc) > 0);
  1888.     
  1889.     // Get the CADocumentRef representing the OD Clipboard object
  1890.     
  1891.     containerHandle = NewHandle(0);
  1892.     
  1893.     if (anyFramesSelected)
  1894.     {
  1895.         clipDoc = CAGetClipboardDocument ();
  1896.     }
  1897.  
  1898.     // Create internal data stream "kCASScrapType".
  1899.     scrapHandle = Doc_CreateCAScrapFromSelection( theDoc, clipDoc, isCut ? kCACloneCut : kCACloneCopy );
  1900.     
  1901.     if (anyFramesSelected)
  1902.     {
  1903.     
  1904.         // Save the clipboard doc container into containerHandle
  1905.         CASaveDocument (clipDoc, NULL, &containerHandle, 0, &length);
  1906.         CACloseDocument (clipDoc);
  1907.         
  1908.     }
  1909.     
  1910.     if (scrapHandle == NULL)
  1911.     {
  1912.         // Single frame case
  1913.         singleFrame = true;
  1914.  
  1915.         // Write the transferDoc to the system scrap as kCAScrapTypeODBentoContainer
  1916.         HLock (containerHandle);
  1917.         
  1918.         // Write the transferDoc container to 
  1919.         theErr = PutScrap(
  1920.                 GetHandleSize (containerHandle),
  1921.                 kCAScrapTypeODBentoContainer, (Ptr)*containerHandle );    // put resource on clipboard
  1922.  
  1923.         HUnlock (containerHandle);
  1924.         DisposeHandle (containerHandle);
  1925.         
  1926.     }
  1927.     else
  1928.     {
  1929.     
  1930.         // Build the composite data stream (length - scrap data - length - doc data)
  1931.         
  1932.         compositeHandle = NewHandle ( (GetHandleSize(scrapHandle) + GetHandleSize (containerHandle)
  1933.                                         + sizeof (long) + sizeof (long)) );
  1934.         
  1935.         HLock( (Handle)compositeHandle );
  1936.     
  1937.         bufferPtr = *compositeHandle;
  1938.             
  1939.         // Write the scrap data length
  1940.         dataLength = GetHandleSize(scrapHandle);
  1941.         BlockMove (&dataLength, bufferPtr, sizeof (long));
  1942.         bufferPtr = (Ptr) ((long) bufferPtr + sizeof (long));
  1943.         
  1944.         HLock( (Handle)scrapHandle );
  1945.     
  1946.         if (dataLength > 0)
  1947.         {
  1948.             // Write the scrap data
  1949.             BlockMove (*scrapHandle, bufferPtr, dataLength);
  1950.             bufferPtr = (Ptr) ((long) bufferPtr + dataLength);
  1951.         }
  1952.         
  1953.         HUnlock ((Handle) scrapHandle);
  1954.         DisposeHandle (scrapHandle);
  1955.             
  1956.     
  1957.         // Write the doc data length
  1958.         HLock( (Handle)containerHandle );
  1959.         dataLength = GetHandleSize(containerHandle);
  1960.         BlockMove (&dataLength, bufferPtr, sizeof (long));
  1961.         bufferPtr = (Ptr) ((long) bufferPtr + sizeof (long));
  1962.             
  1963.         
  1964.         if (dataLength > 0)
  1965.         {
  1966.             // Write the doc data
  1967.             BlockMove (*containerHandle, bufferPtr, dataLength);
  1968.             bufferPtr = (Ptr) ((long) bufferPtr + dataLength);
  1969.         }
  1970.         
  1971.         HUnlock ((Handle) containerHandle);
  1972.         DisposeHandle (containerHandle);
  1973.     
  1974.         theErr = PutScrap(
  1975.                     GetHandleSize (compositeHandle),
  1976.                     kCACASScrapType, (Ptr)*compositeHandle );    // put resource on clipboard
  1977.     
  1978.         if (theErr)
  1979.             Error_ReportOperationError (kCASErrSystemScrapIO);
  1980.     
  1981.         HUnlock( (Handle)compositeHandle );
  1982.         DisposeHandle( compositeHandle );
  1983.     }
  1984.     
  1985.     //    
  1986.     // write PICT flavor
  1987.     //
  1988.     
  1989.     pictHandle = Doc_CreateSelectionPicture (theDoc);
  1990.     length = GetHandleSize ((Handle)pictHandle);
  1991.     HLock ((Handle) pictHandle);
  1992.  
  1993.     theErr = PutScrap(
  1994.                 GetHandleSize ((Handle)pictHandle),
  1995.                 kPICTType, (Ptr)*pictHandle );    // put resource on clipboard
  1996.     HUnlock ((Handle) pictHandle);
  1997.     KillPicture (pictHandle);
  1998.  
  1999.     // make sure the selection is visible in the window.
  2000.     Win_ShowSelection( Doc_GetWindow( theDoc ) );
  2001. }
  2002.  
  2003. #else // CALIB_FRIENDLY_DATA_TRANSFER
  2004.  
  2005. //---------------------------------------------------------------------------
  2006. // Doc_CopyMenu - CALib Friendly version
  2007. //
  2008. // CA writes all scrap formats to the CALib clipboard document.
  2009. // When the clipboard document is closed a scrap type of 'odcn' is added to the
  2010. //  system scrap.  This allow other OpenDoc parts to read it.
  2011. // In order to facilate transfer to other non-OpenDoc application, CAExportClipboard()
  2012. //     must be called on a suspend event.
  2013.  
  2014. void Doc_CopyMenu(
  2015.     DocPtr    theDoc, Boolean isCut )
  2016. {
  2017. Handle            scrapHandle;
  2018. CASize            length;
  2019. CADocumentRef    clipDoc;
  2020. PicHandle        pictHandle;
  2021. char            pictTypeStr[256];
  2022.  
  2023. #ifdef USE_CALIB
  2024. {
  2025.     
  2026.     // Get the CADocumentRef representing the OD Clipboard object
  2027.     clipDoc = CAGetClipboardDocument();
  2028.         
  2029.     // Create internal data stream "kCASScrapType".
  2030.     scrapHandle = Doc_CreateCAScrapFromSelection( theDoc, clipDoc, isCut ? kCACloneCut : kCACloneCopy );
  2031.     
  2032.     CAAddKind(clipDoc, kCACASScrapTypeStr);
  2033.     
  2034. }
  2035. #else
  2036.  
  2037.     // Copy our own format "kCASScrapType" data to the scrap
  2038.     scrapHandle = Doc_CreateScrapFromSelection( theDoc );
  2039.     
  2040. #endif
  2041.  
  2042.     // Note:  If scrapHandle == nil then we do nothing.  A scrap type of
  2043.     // kODScrapTypeODBentoContainer is added to the system scrap by default.
  2044.     
  2045.     if (scrapHandle != nil)
  2046.     {
  2047.         HLock( (Handle)scrapHandle );
  2048.         
  2049. #ifdef USE_CALIB
  2050.  
  2051.         length = GetHandleSize (scrapHandle);
  2052.         CAWrite (clipDoc, (char*)*scrapHandle, &length);
  2053.         
  2054. #else
  2055.         theErr =
  2056.             PutScrap(
  2057.                 GetHandleSize (scrapHandle),
  2058.                 kCASScrapType, (Ptr)*scrapHandle );    // put resource on clipboard
  2059.                 
  2060. #endif
  2061.  
  2062.         DisposeHandle( scrapHandle );
  2063.     }
  2064.     
  2065.     // write PICT flavor
  2066.     pictHandle = Doc_CreateSelectionPicture (theDoc);
  2067.     length = GetHandleSize ((Handle)pictHandle);
  2068.     HLock ((Handle) pictHandle);
  2069.  
  2070. #ifdef USE_CALIB
  2071.     strcpy (pictTypeStr, kODAppleScrapTypePrefix);
  2072.     strcat (pictTypeStr, "PICT");
  2073.     CAAddKind (clipDoc, pictTypeStr);
  2074.     CAWrite (clipDoc, (char*)*pictHandle, &length);
  2075.     CACloseDocument (clipDoc);
  2076. #else
  2077.  
  2078.     theErr = PutScrap(GetHandleSize (pictHandle),
  2079.                 kPICTType, (Ptr)*pictHandle );    // put resource on clipboard
  2080.  
  2081. #endif
  2082.  
  2083.     HUnlock ((Handle) pictHandle);
  2084.     KillPicture (pictHandle);
  2085.  
  2086.     // make sure the selection is visible in the window.
  2087.     Win_ShowSelection( Doc_GetWindow( theDoc ) );
  2088. }
  2089.  
  2090. #endif
  2091.  
  2092. #if CALIB_SAVVY_DATA_TRANSFER
  2093.  
  2094. //---------------------------------------------------------------------------
  2095. // Doc_PasteMenu - CALib friendly version
  2096. //
  2097. // Examine the system scrap for types available.  A type of 'odcn' indicates
  2098. //     a part on the clipboard
  2099.  
  2100. void Doc_PasteMenu(
  2101.     DocPtr    theDoc )
  2102. {
  2103. PicHandle        thePicture;
  2104. Handle            scrapHandle;
  2105. long            scrapLength, scrapOffset;
  2106. long            scrapOff = 0;
  2107. ElemPtr            elem;
  2108. Handle            compositeHandle;
  2109. Handle            docHandle;
  2110. long            length;
  2111.  
  2112.     // if the file is locked, beep and get out.
  2113.     // $$$$$ the paste menu should be disabled if the file is locked, so
  2114.     // we should never get here.
  2115.     if (theDoc->fileLocked)
  2116.     {
  2117.         SysBeep(2);
  2118.         return;
  2119.     }
  2120.  
  2121.     // First check for our internal scrap format
  2122.     if (CAUtil_ScrapHasType (kCACASScrapType, &scrapOffset, &length))
  2123.     {
  2124.         CADocumentRef    transferDoc = NULL;
  2125.         Ptr                bufferPtr;
  2126.         long            docOffset;
  2127.         
  2128.         compositeHandle = NewHandle( 0L );
  2129.         length = GetScrap( compositeHandle, kCACASScrapType, &scrapOffset );
  2130.  
  2131.         HLock (compositeHandle);
  2132.         
  2133.         bufferPtr = *compositeHandle;
  2134.         
  2135.         // Read the scrap data length
  2136.         BlockMove (bufferPtr, &scrapLength, sizeof (long));
  2137.         bufferPtr = (Ptr) ((long) bufferPtr + sizeof (long));
  2138.         
  2139.         // Read the scrap data
  2140.         scrapHandle = NewHandle (scrapLength);
  2141.         HLock (scrapHandle);
  2142.         BlockMove (bufferPtr, *scrapHandle, scrapLength);
  2143.         HUnlock (scrapHandle);
  2144.         bufferPtr = (Ptr) ((long) bufferPtr + scrapLength);
  2145.         
  2146.         // Read the CADocument length
  2147.         BlockMove (bufferPtr, &length, sizeof (long));
  2148.         
  2149.         if (length > 0)
  2150.         {
  2151.         
  2152.             // Compute the CADocument stream offset
  2153.             docOffset = sizeof (long) + scrapLength + sizeof (long);
  2154.         
  2155.             // open the CADocument from the handle
  2156.             transferDoc =  CAOpenDocument (NULL, compositeHandle, docOffset, length);
  2157.         
  2158.         }
  2159.         
  2160.         Doc_SaveUndo( theDoc );
  2161.         Doc_SetDirty( theDoc, true );
  2162.  
  2163.         //clipDoc = CAGetClipboardDocument(theDoc->partDocRef, kCAClonePaste);
  2164.         
  2165.         // Add the content
  2166.         Doc_AddItemsFromCAScrap( theDoc, scrapHandle,  &(theDoc->insertionPoint), transferDoc,
  2167.                                 kCAClonePaste );
  2168.  
  2169.         Win_ShowSelection( Doc_GetWindow( theDoc ) );
  2170.         
  2171.         // Cleanup
  2172.         DisposeHandle( scrapHandle );
  2173.         DisposeHandle (compositeHandle);
  2174.         
  2175.         if (transferDoc)
  2176.             CACloseDocument (transferDoc);
  2177.  
  2178.     }
  2179.  
  2180.     
  2181.     // kODScrapTypeODBentoContainer indicates an OD container
  2182.     
  2183.     // Note: for the CALib friendly version of clipboard operations, CASample writes
  2184.     // the kCACASScrapType data directly to the system scrap, so if there
  2185.     // is a container on the clipboard it definitely is not a proxy doc,
  2186.     // so we check only for a pict part to incorporate, embed anything else.
  2187.     else if (CAUtil_ScrapHasType (kCAScrapTypeODBentoContainer, &scrapOffset, &length))
  2188.     {
  2189.     
  2190.         CADocumentRef    clipDoc;
  2191.         CASize            scrapSize;
  2192.         char            pictTypeStr[256];
  2193.             
  2194.         // Set up PICT value name
  2195.         strcpy (pictTypeStr, kODAppleScrapTypePrefix);
  2196.         strcat (pictTypeStr, "PICT");
  2197.  
  2198.         // Get the container stream
  2199.         scrapHandle = NewHandle( 0L );
  2200.         scrapLength = GetScrap( scrapHandle, kCAScrapTypeODBentoContainer, &scrapOffset );
  2201.  
  2202.         // Open it
  2203.         clipDoc = CAOpenDocument (NULL, scrapHandle, 0, 0);
  2204.  
  2205.         if (CAUseKind (clipDoc, pictTypeStr, 0))
  2206.         {
  2207.         
  2208.             // incoroporate PICT
  2209.             CASetOffset (clipDoc, 0);
  2210.             scrapSize = CAGetSize (clipDoc);
  2211.                 
  2212.             thePicture = (PicHandle) NewHandle (scrapSize);
  2213.             HLock ((Handle) thePicture);
  2214.             CARead (clipDoc, (char*) *thePicture, &scrapSize);
  2215.             HUnlock ((Handle)thePicture);
  2216.  
  2217.             elem = Doc_AddItemPict(theDoc, thePicture,  theDoc->insertionPoint);
  2218.  
  2219.             Elem_SetSelected (elem, true);
  2220.             Win_ShowSelection( Doc_GetWindow( theDoc ) );
  2221.             KillPicture ( thePicture );
  2222.  
  2223.         }
  2224.         else
  2225.         {
  2226.             CAUtil_EmbedODContainerFromCADocument(theDoc, clipDoc,  theDoc->insertionPoint);
  2227.         }
  2228.         
  2229.         CACloseDocument (clipDoc);
  2230.         
  2231.     }
  2232.  
  2233.  
  2234.     
  2235.     // Now check the scrap for a picture
  2236.  
  2237.     else if (CAUtil_ScrapHasType (kPICTType, &scrapOffset, &scrapLength))
  2238.     {
  2239.  
  2240.         thePicture = (PicHandle) NewHandle (0);
  2241.         scrapLength = GetScrap( (Handle) thePicture, kPICTType, &scrapOffset );
  2242.  
  2243.         // Get the PICT on the clipboard
  2244.         // if we got the picture, continue
  2245.         Doc_SaveUndo( theDoc );
  2246.         Doc_SetDirty( theDoc, true );
  2247.  
  2248.         elem = Doc_AddItemPict( theDoc, thePicture, theDoc->insertionPoint); 
  2249.  
  2250.         Win_ShowSelection( Doc_GetWindow( theDoc ) );
  2251.         KillPicture( thePicture );
  2252.     }
  2253.     
  2254.     else
  2255.     {
  2256.         SysBeep(2);
  2257.     }
  2258.     
  2259. }
  2260.  
  2261. #else
  2262.  
  2263. //---------------------------------------------------------------------------
  2264. // Doc_PasteMenu - CALib savvy version
  2265. // 
  2266. //    first check for a scrap type of 'odcn', if present, examine the kind's
  2267. //  available from the CADocument.
  2268.  
  2269. void Doc_PasteMenu(
  2270.     DocPtr    theDoc )
  2271. {
  2272. PicHandle        thePicture;
  2273. Handle            scrapHandle;
  2274. long            scrapLength, scrapOffset;
  2275. long            scrapOff = 0;
  2276. ElemPtr            elem;
  2277. short            i;
  2278.  
  2279.     // if the file is locked, beep and get out.
  2280.     // $$$$$ the paste menu should be disabled if the file is locked, so
  2281.     // we should never get here.
  2282.     if (theDoc->fileLocked)
  2283.     {
  2284.         SysBeep(2);
  2285.         return;
  2286.     }
  2287.  
  2288.     
  2289. #ifdef USE_CALIB
  2290.  
  2291.     // kODScrapTypeODBentoContainer indicates the OD Clipboard.
  2292.     
  2293.     if (CAUtil_ScrapHasType (kCAScrapTypeODBentoContainer, &scrapOffset, &scrapLength))
  2294.     {
  2295.     
  2296.         CADocumentRef    clipDoc;
  2297.         short            numKinds;
  2298.         CAISOStr        partKind;
  2299.         CASize            scrapSize;
  2300.  
  2301.         // Get the container stream
  2302.         scrapHandle = NewHandle( 0L );
  2303.         scrapLength = GetScrap( scrapHandle, kCAScrapTypeODBentoContainer, &scrapOffset );
  2304.  
  2305.         // Open the container
  2306.         clipDoc = CAOpenDocument (NULL, scrapHandle, 0, scrapLength);
  2307.          
  2308.         numKinds = CAGetKindCount (clipDoc);
  2309.          
  2310.         for (i = 1; i <= numKinds; ++i)
  2311.         {
  2312.         
  2313.             char        pictTypeStr[256];
  2314.             
  2315.             strcpy (pictTypeStr, kODAppleScrapTypePrefix);
  2316.             strcat (pictTypeStr, "PICT");
  2317.  
  2318.             // Make incorporate or embed decision
  2319.             
  2320.             partKind = CAGetNthKind (clipDoc, i);
  2321.  
  2322.             // is it CASample's scrap type
  2323.             if (bCStrCmp (partKind, kCACASScrapTypeStr))
  2324.             {
  2325.             
  2326.                 CAUseKind (clipDoc, partKind, 0);
  2327.                 
  2328.                 CASetOffset (clipDoc, 0);
  2329.                 scrapSize = CAGetSize (clipDoc);
  2330.                 
  2331.                 scrapHandle = NewHandle (scrapSize);
  2332.                 CARead (clipDoc, *scrapHandle, &scrapSize);
  2333.                 
  2334.                 Doc_AddItemsFromCAScrap( theDoc, scrapHandle, &(theDoc->insertionPoint), clipDoc,
  2335.                                             kCAClonePaste );
  2336.     
  2337.                 Win_ShowSelection( Doc_GetWindow( theDoc ) );
  2338.                 DisposeHandle( scrapHandle );
  2339.     
  2340.     
  2341.             }
  2342.             
  2343.             // is it a PICT
  2344.             else if (bCStrCmp (partKind, pictTypeStr))
  2345.             {
  2346.             
  2347.                 CAUseKind (clipDoc, partKind, 0);
  2348.                 
  2349.                 CASetOffset (clipDoc, 0);
  2350.                 scrapSize = CAGetSize (clipDoc);
  2351.                 
  2352.                 thePicture = (PicHandle) NewHandle (scrapSize);
  2353.                 HLock ((Handle) thePicture);
  2354.                 CARead (clipDoc, (char*) *thePicture, &scrapSize);
  2355.                 HUnlock ((Handle)thePicture);
  2356.  
  2357.                 elem = Doc_AddItemPict(theDoc, thePicture,  theDoc->insertionPoint);
  2358.  
  2359.                 Elem_SetSelected (elem, true);
  2360.                 Win_ShowSelection( Doc_GetWindow( theDoc ) );
  2361.                 KillPicture ( thePicture );
  2362.     
  2363.     
  2364.             }
  2365.  
  2366.             // Can't incorporate, so embed
  2367.             else
  2368.             {
  2369.                 CAUtil_EmbedODContainerFromCADocument(theDoc, clipDoc, theDoc->insertionPoint);
  2370.             }
  2371.         
  2372.             DisposePtr (partKind);
  2373.  
  2374.         }
  2375.         
  2376.         CACloseDocument (clipDoc);
  2377.         
  2378.     }
  2379.  
  2380.  
  2381.     // No OpenDoc clipboard, check for other types.
  2382.     else if (CAUtil_ScrapHasType (kCACASScrapType, &scrapOffset, &scrapLength))
  2383.     {
  2384.         CADocumentRef    clipDoc;
  2385.         
  2386.         scrapHandle = NewHandle( 0L );
  2387.         scrapLength = GetScrap( scrapHandle, kCACASScrapType, &scrapOffset );
  2388.  
  2389.         Doc_SaveUndo( theDoc );
  2390.         Doc_SetDirty( theDoc, true );
  2391.  
  2392.         clipDoc = CAGetClipboardDocument(theDoc->partDocRef, kCAClonePaste);
  2393.         
  2394.         Doc_AddItemsFromCAScrap( theDoc, scrapHandle,  &(theDoc->insertionPoint), clipDoc,
  2395.                                 kCAClonePaste );
  2396.  
  2397.         Win_ShowSelection( Doc_GetWindow( theDoc ) );
  2398.         DisposeHandle( scrapHandle );
  2399.         CACloseDocument (clipDoc);
  2400.  
  2401.     }
  2402.  
  2403.     
  2404.  
  2405. #else
  2406.  
  2407.     if (CAUtil_ScrapHasType (kCASScrapType, &scrapOffset, &scrapLength))
  2408.     {
  2409.         scrapHandle = NewHandle( 0L );
  2410.         scrapLength = GetScrap( scrapHandle, kCASScrapType, &scrapOffset );
  2411.  
  2412.         Doc_SaveUndo( theDoc );
  2413.         Doc_SetDirty( theDoc, true );
  2414.  
  2415.         Doc_AddItemsFromScrap( theDoc, scrapHandle,  &(theDoc->insertionPoint) );
  2416.  
  2417.         Win_ShowSelection( Doc_GetWindow( theDoc ) );
  2418.  
  2419.         DisposeHandle( scrapHandle );
  2420.  
  2421.     }
  2422.     
  2423. #endif
  2424.     
  2425.     // Now check the scrap for a picture
  2426.  
  2427.     else if (CAUtil_ScrapHasType (kPICTType, &scrapOffset, &scrapLength))
  2428.     {
  2429.  
  2430.         thePicture = (PicHandle) NewHandle (0);
  2431.         scrapLength = GetScrap( (Handle) thePicture, kPICTType, &scrapOffset );
  2432.  
  2433.         // Get the PICT on the clipboard
  2434.         // if we got the picture, continue
  2435.         Doc_SaveUndo( theDoc );
  2436.         Doc_SetDirty( theDoc, true );
  2437.  
  2438.         elem = Doc_AddItemPict( theDoc, thePicture, theDoc->insertionPoint); 
  2439.  
  2440.         Win_ShowSelection( Doc_GetWindow( theDoc ) );
  2441.         KillPicture( thePicture );
  2442.     }
  2443.     
  2444.     else
  2445.     {
  2446.         SysBeep(2);
  2447.     }
  2448.     
  2449. }
  2450.  
  2451. #endif
  2452.  
  2453.  
  2454. //---------------------------------------------------------------------------
  2455. // Doc_ClearMenu - clear the selection from the document.
  2456. // assume it's our window and there is a selection.
  2457.  
  2458. void Doc_ClearMenu(
  2459.     DocPtr    theDoc )
  2460. {
  2461.     // if the file is locked, beep and get out.
  2462.     // $$$$$ the clear menu should be disabled if the file is locked, so
  2463.     // we should never get here.
  2464.     if (theDoc->fileLocked)
  2465.         SysBeep(2);
  2466.     else
  2467.     {
  2468.         Doc_SaveUndo( theDoc );
  2469.  
  2470.         Doc_SetDirty( theDoc, true );
  2471.         Doc_DeleteCurrentSelection( theDoc );
  2472.  
  2473.         Win_ShowSelection( Doc_GetWindow( theDoc ) );
  2474.     }
  2475. }
  2476.  
  2477. //---------------------------------------------------------------------------
  2478. // Doc_SelectAllMenu - 
  2479. // assume it's our window and there is at least one item.
  2480.  
  2481. void Doc_SelectAllMenu(
  2482.     DocPtr    theDoc )
  2483. {
  2484.     Doc_SelectAllElements( theDoc, true );
  2485. }
  2486.  
  2487.  
  2488. //---------------------------------------------------------------------------
  2489. // Doc_RectDocToGlobal - 
  2490.  
  2491. void Doc_RectDocToGlobal(
  2492.     DocPtr    theDoc,
  2493.     Rect    *theRect )
  2494. {
  2495. GrafPtr        savedPort;
  2496. WindowPtr    theWindow;
  2497. Point        saveOrigin;
  2498.  
  2499.     theWindow = Doc_GetWindow( theDoc );
  2500.  
  2501.     GetPort( &savedPort );
  2502.     SetPort( theWindow );
  2503.  
  2504.     GetOrigin( &saveOrigin );
  2505.     Doc_SetGrafOrigin( theDoc );
  2506.  
  2507.     RectLocalToGlobal( theRect );
  2508.  
  2509.     SetOrigin( saveOrigin.h, saveOrigin.v );
  2510.     SetPort( savedPort );
  2511. }
  2512.  
  2513. //---------------------------------------------------------------------------
  2514. // Doc_RgnDocToGlobal - 
  2515.  
  2516. void Doc_RgnDocToGlobal( DocPtr theDoc, RgnHandle theRgn )
  2517. {
  2518. GrafPtr        savedPort;
  2519. WindowPtr    theWindow;
  2520. Point        saveOrigin;
  2521.  
  2522.     theWindow = Doc_GetWindow( theDoc );
  2523.  
  2524.     GetPort( &savedPort );
  2525.     SetPort( theWindow );
  2526.  
  2527.     GetOrigin( &saveOrigin );
  2528.     Doc_SetGrafOrigin( theDoc );
  2529.  
  2530.     RgnLocalToGlobal( theRgn );
  2531.  
  2532.     SetOrigin( saveOrigin.h, saveOrigin.v );
  2533.     SetPort( savedPort );
  2534. }
  2535.  
  2536. void Doc_HandleSelectionRect (DocPtr theDoc, Point startPt)
  2537. {
  2538.     WindowPtr        window;
  2539.     Rect            selectionBox;
  2540.     Rect            oldBox;
  2541.     Point            theLoc, localStartPt;
  2542.     Point            lastLoc = {0,0};
  2543.     GrafPtr            savePort;
  2544.     short            count = 0, i;
  2545.     ElemPtr            elem = NULL;
  2546.     Rect            elemRect;
  2547.     
  2548.     if (!WaitMouseMoved( startPt ))
  2549.         return;
  2550.  
  2551.     window = Doc_GetWindow (theDoc);
  2552.     
  2553.     GetPort(&savePort);
  2554.     SetPort(window);
  2555.  
  2556.     localStartPt = startPt;
  2557.     GlobalToLocal (&localStartPt);
  2558.     
  2559.     SetRect (&oldBox, 0,0,0,0);
  2560.  
  2561.     PenMode(patXor);
  2562.     PenPat(&(qd.gray));
  2563.     
  2564.     while (WaitMouseUp())
  2565.     {
  2566.         GetMouse(&theLoc);
  2567.         
  2568.         if (!EqualPt (theLoc, lastLoc))
  2569.         {
  2570.             Pt2Rect (theLoc, localStartPt, &selectionBox);
  2571.             
  2572.             FrameRect(&oldBox);
  2573.             FrameRect(&selectionBox);
  2574.         
  2575.             lastLoc = theLoc;
  2576.             oldBox = selectionBox;
  2577.         }
  2578.     }
  2579.     
  2580.     FrameRect(&oldBox);
  2581.     
  2582.     PenPat(&(qd.gray));
  2583.     PenMode(patCopy);
  2584.  
  2585.     count = ElemColl_GetCount (theDoc->contentColl);
  2586.     for (i=1; i <= count; i++)
  2587.     {
  2588.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  2589.         Elem_GetLocatedRect (elem, &elemRect);
  2590.         
  2591.         if ( PtInRect ( *((Point*) &(elemRect.top)), &oldBox) &&
  2592.              PtInRect ( *((Point*) &(elemRect.bottom)), &oldBox))
  2593.         {
  2594.         
  2595.             Elem_SetSelected (elem, true);
  2596.         
  2597.         }
  2598.         
  2599.     }
  2600.  
  2601.     SetPort (savePort);
  2602. }
  2603.  
  2604.  
  2605. //===========================================================================
  2606. #pragma mark '     Frame management
  2607. //===========================================================================
  2608.  
  2609. #ifdef USE_CALIB
  2610.  
  2611. ElemPtr Doc_AddEmbeddedFrame (DocPtr theDoc, CAFrameRef frameRef, Point location)
  2612. {
  2613. RgnHandle        theRgn;
  2614. ElemPtr            elem;
  2615. Rect            theRect;
  2616. Handle            elemData;
  2617.  
  2618.     theRgn = CAGetFrameRgn (theDoc->partDocRef, frameRef);
  2619.     theRect = (**theRgn).rgnBBox;
  2620.  
  2621.     elem = Elem_New ((Handle)frameRef, kFrameElemType, theRect, location);
  2622.     ElemColl_AddElem (theDoc->contentColl, elem);
  2623.     
  2624.     return (elem);
  2625.  
  2626. }
  2627.  
  2628. //---------------------------------------------------------------------------
  2629.  
  2630. ElemPtr Doc_FindElemForFrameRef (DocPtr theDoc, CAFrameRef frameRef)
  2631. {
  2632. long        i;
  2633. short        count = 0;
  2634. ElemPtr        elem = NULL;
  2635. Boolean        matched = false;
  2636.  
  2637.     count = ElemColl_GetCount (theDoc->contentColl);
  2638.     for (i=1; i <= count; i++)
  2639.     {
  2640.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  2641.         if (frameRef == (CAFrameRef) elem->elemData)
  2642.         {
  2643.             matched = true;
  2644.             break;
  2645.         }
  2646.         
  2647.     }
  2648.     
  2649.     if (!matched) elem = NULL;
  2650.     return (elem);
  2651.  
  2652. }
  2653.  
  2654. #endif
  2655.  
  2656. //---------------------------------------------------------------------------
  2657. // Doc_CreateCAScrapFromSelection() - Generates and returns a handle to
  2658. //     scrap data.  If the selection consists of a single embedded frame
  2659. //  then a NULL handle is returned.
  2660. //
  2661. //     CAScrap stream format:
  2662. //
  2663. //        Selection Rect Origin (Point)
  2664. //        Selection Element Count (long)
  2665. //        n Content Element Streams
  2666. //
  2667. Handle Doc_CreateCAScrapFromSelection(
  2668.     DocPtr    theDoc, CADocumentRef transferDoc, CACloneKind cloneKind )
  2669. {
  2670. Handle        scrapData;
  2671. Ptr            scrapOffset;
  2672. Rect        boundsRect;
  2673. Point        origin;
  2674. OSErr        theErr;
  2675. long        scrapSize, i;
  2676. IOStream    ioStream;
  2677. CAFrameRef    newFrameRef;
  2678. ElemPtr        frameElem;
  2679. long        frameCount            = 0;
  2680. short        count                = 0;
  2681. ElemPtr        elem                = NULL;
  2682. long        selectedElemCount    = 0;
  2683. long        selectedFrameCount    = 0;
  2684. Boolean        isRoot                = false;
  2685. CACloneKey    key                    = NULL;
  2686.  
  2687.     scrapSize = 0L;
  2688.  
  2689.     Doc_CalcSelectionBounds( theDoc, &boundsRect );
  2690.     origin.h = boundsRect.left;
  2691.     origin.v = boundsRect.top;
  2692.  
  2693.     // Compute the size in bytes needed for the scrap
  2694.     
  2695.     scrapSize = sizeof (Point);            // Origin
  2696.     scrapSize += sizeof (long);            // element count
  2697.     
  2698.     count = ElemColl_GetCount (theDoc->contentColl);
  2699.     for (i=1; i <= count; i++)
  2700.     {
  2701.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  2702.         
  2703.         if (Elem_GetSelected (elem))
  2704.         {
  2705.             ++selectedElemCount;
  2706.             scrapSize += Elem_SpaceRequired (elem);
  2707.             if (elem->elemType == kFrameElemType) ++selectedFrameCount;
  2708.         }
  2709.     }
  2710.     
  2711.         
  2712.     // Allocate the scrap buffer
  2713.  
  2714.     scrapData = NewHandle( scrapSize );
  2715.     theErr = MemError();
  2716.     if (theErr != noErr)
  2717.         return nil;
  2718.  
  2719.     scrapOffset = *scrapData;
  2720.  
  2721.     BlockMoveData( &origin, scrapOffset, sizeof(Point) );
  2722.     scrapOffset += sizeof(Point);
  2723.  
  2724.     BlockMoveData( &selectedElemCount, scrapOffset, (long)sizeof(long) );
  2725.     scrapOffset += sizeof(long);
  2726.      
  2727.     ioStream.type = memoryStream;
  2728.     ioStream.theDoc = theDoc;
  2729.     ioStream.buffer = (Ptr) scrapOffset;
  2730.     
  2731.     // Write item data
  2732.  
  2733. #ifdef USE_CALIB
  2734.  
  2735.     if ((selectedElemCount == 1) && (selectedFrameCount == 1))
  2736.     {
  2737.         isRoot = true;
  2738.         key = CABeginClone (theDoc->partDocRef, transferDoc, cloneKind);
  2739.     }
  2740.     else if (selectedFrameCount > 0)
  2741.     {
  2742.         key = CABeginClone (theDoc->partDocRef, transferDoc, cloneKind);
  2743.     }
  2744. #endif
  2745.  
  2746.     for (i=1; i <= count; i++)
  2747.     {
  2748.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  2749.         
  2750.         if (Elem_GetSelected (elem) && elem->elemType != kFrameElemType)
  2751.         {
  2752.             Elem_Write (elem, &ioStream);
  2753.         }
  2754.         else if (Elem_GetSelected (elem))
  2755.         {
  2756.             newFrameRef = CACloneFrameRef ((CAFrameRef)(elem->elemData), theDoc->partDocRef,
  2757.                 transferDoc, isRoot, key);
  2758.                 
  2759.             frameElem = Elem_New ((Handle) newFrameRef, kFrameElemType, elem->contentRect, elem->location);
  2760.             Elem_Write (frameElem, &ioStream);
  2761.             DisposePtr ((Ptr) frameElem);
  2762.         }
  2763.         
  2764.         
  2765.         
  2766.     }
  2767.     
  2768. #ifdef USE_CALIB
  2769.  
  2770.     if (key)
  2771.         CAEndClone (theDoc->partDocRef, transferDoc, key);
  2772.  
  2773.     if (isRoot)
  2774.     {
  2775.         DisposeHandle( scrapData );
  2776.         scrapData = NULL;
  2777.     }
  2778.     
  2779. #endif
  2780.  
  2781.     return scrapData;
  2782.     
  2783. }
  2784.  
  2785. //---------------------------------------------------------------------------
  2786. // Doc_AddItemsFromScrap - 
  2787. //
  2788. // origin specifies the top-left corner of the new selection rect
  2789.  
  2790. void Doc_AddItemsFromCAScrap(
  2791.     DocPtr            theDoc,
  2792.     Handle            theScrap,
  2793.     Point*            origin,
  2794.     CADocumentRef    transferDoc,
  2795.     CACloneKind        cloneKind)
  2796. {
  2797. Ptr                offsetPtr;
  2798. Point            location, sourceOrigin;
  2799. long            i;
  2800. Boolean            lockState;
  2801. ElemPtr            elem;
  2802. short            count;
  2803. long            elemCount;
  2804. IOStream        ioStream;
  2805. CACloneKey        key = NULL;
  2806. CAFrameRef        newFrameRef;
  2807. CATransform        extTransform;
  2808. CAVisFrame        visFrame;
  2809. ElemCollPtr        tempColl;
  2810.  
  2811.     lockState = HGetState (theScrap);
  2812.     HLock (theScrap);
  2813.     
  2814.     offsetPtr = *theScrap;
  2815.     BlockMoveData( offsetPtr, (Ptr)&sourceOrigin, (long)sizeof(Point) );
  2816.     offsetPtr += sizeof(Point);
  2817.  
  2818.     BlockMoveData( offsetPtr, (Ptr)&elemCount, (long)sizeof(long) );
  2819.     offsetPtr += sizeof(long);
  2820.  
  2821.     Doc_SelectAllElements( theDoc, false );
  2822.  
  2823.     ioStream.type = memoryStream;
  2824.     ioStream.theDoc = theDoc;
  2825.     ioStream.buffer = (Ptr) offsetPtr;
  2826.  
  2827.     // Create list to hold transfer elemPtr's
  2828.     
  2829.     tempColl = (ElemCollPtr) NewPtr (sizeof (ElemColl));
  2830.     ElemColl_Init (tempColl, NULL);
  2831.     
  2832.     // Read in the elements
  2833.     for (i=0; i<elemCount; ++i)
  2834.     {
  2835.         
  2836.         // Read the element from ioStream
  2837.         elem = Elem_Read (&ioStream);
  2838.         ElemColl_AddElem (theDoc->contentColl, elem);
  2839.         
  2840.         ElemColl_AddElemTemp (tempColl, elem);
  2841.         
  2842.         // Clone the CAFrameRef
  2843.  
  2844. #ifdef USE_CALIB
  2845.         if (elem->elemType == kFrameElemType)
  2846.         {
  2847.  
  2848.             if (!key)
  2849.                 key = CABeginClone (transferDoc, theDoc->partDocRef, cloneKind);
  2850.  
  2851.             newFrameRef = CACloneFrameRef ((CAFrameRef)elem->elemData, transferDoc,
  2852.                 theDoc->partDocRef, false, key);
  2853.             
  2854.             elem->elemData = (Handle) newFrameRef;
  2855.  
  2856.         }
  2857. #endif
  2858.  
  2859.         // Set the new location
  2860.         
  2861.         Elem_GetLocation (elem, &location);
  2862.         if (origin)
  2863.         {
  2864.             location.h = location.h - sourceOrigin.h + (*origin).h;
  2865.             location.v = location.v - sourceOrigin.v + (*origin).v;
  2866.         }
  2867.         Elem_SetLocation (elem, location);
  2868.  
  2869.  
  2870.     }
  2871.     
  2872. #ifdef USE_CALIB
  2873.     if (key)
  2874.         CAEndClone (transferDoc, theDoc->partDocRef, key);
  2875. #endif
  2876.  
  2877.     count = ElemColl_GetCount (tempColl);
  2878.     
  2879.     for (i = 1; i<= elemCount; ++i)
  2880.     {
  2881.         elem = ElemColl_GetNthElem (tempColl, i);
  2882.         
  2883.         // Set the frame as visible
  2884.         Elem_SetVisible (elem, true);
  2885.         Elem_SetSelected (elem, true);
  2886.     }
  2887.     
  2888.     ElemColl_Free (tempColl);
  2889.     DisposePtr ((Ptr) tempColl);
  2890.     
  2891.     Doc_SetDirty( theDoc, true );
  2892.     HSetState (theScrap, lockState);
  2893.  
  2894. }
  2895.  
  2896.  
  2897. void GetPlatformScrapTypeList (ResType typeArray[])
  2898. {
  2899.  
  2900. Handle            hData = NULL;
  2901. long            scrapOffset = 0;
  2902. PScrapStuff        scrapInfo;
  2903. Handle            hScrap;
  2904. short            i = 0;
  2905.  
  2906.     LoadScrap();
  2907.  
  2908.     scrapInfo = InfoScrap();
  2909.     hScrap = scrapInfo->scrapHandle;
  2910.     
  2911.     while ( scrapOffset < scrapInfo->scrapSize )
  2912.     {
  2913.         long        scrapTypeLength;
  2914.         ResType        theType;
  2915.         long        realOffset;
  2916.     
  2917.         // There is more in the scrap
  2918.         theType = *(ResTypePtr)(((long) *hScrap) + scrapOffset);
  2919.         scrapTypeLength = GetScrap((Handle) hData, theType, (long*) &realOffset);
  2920.         typeArray[i++] = theType;
  2921.         
  2922.         if ( realOffset < scrapOffset ) break;
  2923.  
  2924.         // The length must be EVEN!
  2925.         if (scrapTypeLength & 1)
  2926.         {
  2927.             scrapTypeLength += 1;
  2928.         }
  2929.         scrapOffset = realOffset + scrapTypeLength;
  2930.     }
  2931.  
  2932.  
  2933.  
  2934. }
  2935.  
  2936.  
  2937.